lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAJZ5v0gLXxvzKcjSFH0Coq_VRE9fiT9AiCD_vsg7x1Gaq62V+A@mail.gmail.com>
Date:   Tue, 7 Dec 2021 20:52:03 +0100
From:   "Rafael J. Wysocki" <rafael@...nel.org>
To:     Chen Yu <yu.c.chen@...el.com>
Cc:     ACPI Devel Maling List <linux-acpi@...r.kernel.org>,
        Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
        "Rafael J. Wysocki" <rafael@...nel.org>,
        Ard Biesheuvel <ardb@...nel.org>, Len Brown <lenb@...nel.org>,
        Ashok Raj <ashok.raj@...el.com>,
        Andy Shevchenko <andriy.shevchenko@...el.com>,
        Mike Rapoport <rppt@...nel.org>,
        Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
        Robert Moore <robert.moore@...el.com>
Subject: Re: [PATCH v11 4/4] tools: Introduce power/acpi/tools/pfru

On Sun, Nov 21, 2021 at 4:18 PM Chen Yu <yu.c.chen@...el.com> wrote:
>
> Introduce a user space tool to make use of the interface exposed by
> Platform Firmware Runtime Update and Telemetry drivers. The users
> can use this tool to do firmware code injection, driver update and
> to retrieve the telemetry data.
>
> Signed-off-by: Chen Yu <yu.c.chen@...el.com>
> ---
> v11:No change since v10.
> v10:No change since v9.
> v9: Add this tool into tools/power/acpi build infrastructure.
>     (Andy Shevchenko)
> v8: Print the length of OEM information if requested.
> v7: No change since v6.
> v6: Simplify the userspace tool to use while loop for getopt_long().
>     (Andy Shevchenko)
> v5: Replace the read() with mmap() so that the userspace
>     could mmap once, and read multiple times. (Greg Kroah-Hartman)
> ---
>  tools/power/acpi/.gitignore          |   1 +
>  tools/power/acpi/Makefile            |  16 +-
>  tools/power/acpi/Makefile.rules      |   2 +-
>  tools/power/acpi/man/pfru.8          | 137 +++++++++

I would call it pfrut, because it is for both the update and telemetry
retrieval.

>  tools/power/acpi/tools/pfru/Makefile |  23 ++
>  tools/power/acpi/tools/pfru/pfru.c   | 417 +++++++++++++++++++++++++++
>  6 files changed, 587 insertions(+), 9 deletions(-)
>  create mode 100644 tools/power/acpi/man/pfru.8
>  create mode 100644 tools/power/acpi/tools/pfru/Makefile
>  create mode 100644 tools/power/acpi/tools/pfru/pfru.c
>
> diff --git a/tools/power/acpi/.gitignore b/tools/power/acpi/.gitignore
> index 0b319fc8bb17..a6f196912999 100644
> --- a/tools/power/acpi/.gitignore
> +++ b/tools/power/acpi/.gitignore
> @@ -2,4 +2,5 @@
>  /acpidbg
>  /acpidump
>  /ec
> +/pfru
>  /include/
> diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
> index a249c50ebf55..2fcf09d3add3 100644
> --- a/tools/power/acpi/Makefile
> +++ b/tools/power/acpi/Makefile
> @@ -9,18 +9,18 @@ include ../../scripts/Makefile.include
>
>  .NOTPARALLEL:
>
> -all: acpidbg acpidump ec
> -clean: acpidbg_clean acpidump_clean ec_clean
> -install: acpidbg_install acpidump_install ec_install
> -uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall
> +all: acpidbg acpidump ec pfru
> +clean: acpidbg_clean acpidump_clean ec_clean pfru_clean
> +install: acpidbg_install acpidump_install ec_install pfru_install
> +uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall pfru_uninstall
>
> -acpidbg acpidump ec: FORCE
> +acpidbg acpidump ec pfru: FORCE
>         $(call descend,tools/$@,all)
> -acpidbg_clean acpidump_clean ec_clean:
> +acpidbg_clean acpidump_clean ec_clean pfru_clean:
>         $(call descend,tools/$(@:_clean=),clean)
> -acpidbg_install acpidump_install ec_install:
> +acpidbg_install acpidump_install ec_install pfru_install:
>         $(call descend,tools/$(@:_install=),install)
> -acpidbg_uninstall acpidump_uninstall ec_uninstall:
> +acpidbg_uninstall acpidump_uninstall ec_uninstall pfru_uninstall:
>         $(call descend,tools/$(@:_uninstall=),uninstall)
>
>  .PHONY: FORCE
> diff --git a/tools/power/acpi/Makefile.rules b/tools/power/acpi/Makefile.rules
> index 2a6c170b57cd..68aa7e92d554 100644
> --- a/tools/power/acpi/Makefile.rules
> +++ b/tools/power/acpi/Makefile.rules
> @@ -9,7 +9,7 @@ objdir := $(OUTPUT)tools/$(TOOL)/
>  toolobjs := $(addprefix $(objdir),$(TOOL_OBJS))
>  $(OUTPUT)$(TOOL): $(toolobjs) FORCE
>         $(ECHO) "  LD      " $(subst $(OUTPUT),,$@)
> -       $(QUIET) $(LD) $(CFLAGS) $(LDFLAGS) $(toolobjs) -L$(OUTPUT) -o $@
> +       $(QUIET) $(LD) $(CFLAGS) $(toolobjs) $(LDFLAGS) -L$(OUTPUT) -o $@
>         $(ECHO) "  STRIP   " $(subst $(OUTPUT),,$@)
>         $(QUIET) $(STRIPCMD) $@
>
> diff --git a/tools/power/acpi/man/pfru.8 b/tools/power/acpi/man/pfru.8
> new file mode 100644
> index 000000000000..d9cda7beaa3c
> --- /dev/null
> +++ b/tools/power/acpi/man/pfru.8
> @@ -0,0 +1,137 @@
> +.TH "PFRU" "8" "October 2021" "pfru 1.0" ""
> +.hy
> +.SH Name
> +.PP
> +pfru \- Platform Firmware Runtime Update tool
> +.SH SYNOPSIS
> +.PP
> +\f[B]pfru\f[R] [\f[I]Options\f[R]]
> +.SH DESCRIPTION
> +.PP
> +The PFRU(Platform Firmware Runtime Update) kernel interface is designed
> +to
> +.PD 0
> +.P
> +.PD
> +interact with the platform firmware interface defined in the
> +.PD 0
> +.P
> +.PD
> +Management Mode Firmware Runtime
> +Update (https://uefi.org/sites/default/files/resources/Intel_MM_OS_Interface_Spec_Rev100.pdf)
> +.PD 0
> +.P
> +.PD
> +\f[B]pfru\f[R] is the tool to interact with the kernel interface.
> +.PD 0
> +.P
> +.PD
> +.SH OPTIONS
> +.TP
> +.B \f[B]\-h\f[R], \f[B]\-\-help\f[R]
> +Display helper information.
> +.TP
> +.B \f[B]\-l\f[R], \f[B]\-\-load\f[R]
> +Load the capsule file into the system.
> +To be more specific, the capsule file will be copied to the
> +communication buffer.
> +.TP
> +.B \f[B]\-s\f[R], \f[B]\-\-stage\f[R]
> +Stage the capsule image from communication buffer into Management Mode
> +and perform authentication.
> +.TP
> +.B \f[B]\-a\f[R], \f[B]\-\-activate\f[R]
> +Activate a previous staged capsule image.
> +.TP
> +.B \f[B]\-u\f[R], \f[B]\-\-update\f[R]
> +Perform both stage and activation actions.
> +.TP
> +.B \f[B]\-q\f[R], \f[B]\-\-query\f[R]
> +Query the update capability.
> +.TP
> +.B \f[B]\-d\f[R], \f[B]\-\-setrev\f[R]
> +Set the revision ID of code injection/driver update.
> +.TP
> +.B \f[B]\-D\f[R], \f[B]\-\-setrevlog\f[R]
> +Set the revision ID of telemetry.
> +.TP
> +.B \f[B]\-G\f[R], \f[B]\-\-getloginfo\f[R]
> +Get telemetry log information and print it out.
> +.TP
> +.B \f[B]\-T\f[R], \f[B]\-\-type\f[R]
> +Set the telemetry log data type.
> +.TP
> +.B \f[B]\-L\f[R], \f[B]\-\-level\f[R]
> +Set the telemetry log level.
> +.TP
> +.B \f[B]\-R\f[R], \f[B]\-\-read\f[R]
> +Read all the telemetry data and print it out.
> +.SH EXAMPLES
> +.PP
> +\f[B]pfru \-G\f[R]
> +.PP
> +log_level:4
> +.PD 0
> +.P
> +.PD
> +log_type:0
> +.PD 0
> +.P
> +.PD
> +log_revid:2
> +.PD 0
> +.P
> +.PD
> +max_data_size:65536
> +.PD 0
> +.P
> +.PD
> +chunk1_size:0
> +.PD 0
> +.P
> +.PD
> +chunk2_size:1401
> +.PD 0
> +.P
> +.PD
> +rollover_cnt:0
> +.PD 0
> +.P
> +.PD
> +reset_cnt:4
> +.PP
> +\f[B]pfru \-q\f[R]
> +.PP
> +code injection image type:794bf8b2\-6e7b\-454e\-885f\-3fb9bb185402
> +.PD 0
> +.P
> +.PD
> +fw_version:0
> +.PD 0
> +.P
> +.PD
> +code_rt_version:1
> +.PD 0
> +.P
> +.PD
> +driver update image type:0e5f0b14\-f849\-7945\-ad81\-bc7b6d2bb245
> +.PD 0
> +.P
> +.PD
> +drv_rt_version:0
> +.PD 0
> +.P
> +.PD
> +drv_svn:0
> +.PD 0
> +.P
> +.PD
> +platform id:39214663\-b1a8\-4eaa\-9024\-f2bb53ea4723
> +.PD 0
> +.P
> +.PD
> +oem id:a36db54f\-ea2a\-e14e\-b7c4\-b5780e51ba3d
> +.PP
> +\f[B]pfru \-l yours.cap \-u \-T 1 \-L 4\f[R]
> +.SH AUTHORS
> +Chen Yu.
> diff --git a/tools/power/acpi/tools/pfru/Makefile b/tools/power/acpi/tools/pfru/Makefile
> new file mode 100644
> index 000000000000..09002a81e10c
> --- /dev/null
> +++ b/tools/power/acpi/tools/pfru/Makefile
> @@ -0,0 +1,23 @@
> +# SPDX-License-Identifier: GPL-2.0+
> +
> +include ../../Makefile.config
> +
> +TOOL = pfru
> +EXTRA_INSTALL = install-man
> +EXTRA_UNINSTALL = uninstall-man
> +
> +CFLAGS += -Wall -O2
> +CFLAGS += -DPFRU_HEADER='"../../../../../include/uapi/linux/pfru.h"'
> +LDFLAGS += -luuid
> +
> +TOOL_OBJS = \
> +       pfru.o
> +
> +include ../../Makefile.rules
> +
> +install-man: $(srctree)/man/pfru.8
> +       $(ECHO) "  INST    " pfru.8
> +       $(QUIET) $(INSTALL_DATA) -D $< $(DESTDIR)$(mandir)/man8/pfru.8
> +uninstall-man:
> +       $(ECHO) "  UNINST  " pfru.8
> +       $(QUIET) rm -f $(DESTDIR)$(mandir)/man8/pfru.8
> diff --git a/tools/power/acpi/tools/pfru/pfru.c b/tools/power/acpi/tools/pfru/pfru.c
> new file mode 100644
> index 000000000000..eeec5043f825
> --- /dev/null
> +++ b/tools/power/acpi/tools/pfru/pfru.c
> @@ -0,0 +1,417 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Platform Firmware Runtime Update tool to do Management
> + * Mode code injection/driver update and telemetry retrieval.

I would be good to say a bit more here, like what interfaces are used
by this tool etc.

> + */
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +#include <getopt.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <uuid/uuid.h>
> +#include PFRU_HEADER
> +
> +char *capsule_name;
> +int action, query_cap, log_type, log_level, log_read, log_getinfo,
> +       revid, log_revid;
> +int set_log_level, set_log_type,
> +       set_revid, set_log_revid;
> +
> +char *progname;
> +
> +#define LOG_ERR                0
> +#define LOG_WARN       1
> +#define LOG_INFO       2
> +#define LOG_VERB       4
> +#define LOG_EXEC_IDX   0
> +#define LOG_HISTORY_IDX        1
> +#define REVID_1                1
> +#define REVID_2                2
> +
> +static int valid_log_level(int level)
> +{
> +       return level == LOG_ERR || level == LOG_WARN ||
> +              level == LOG_INFO || level == LOG_VERB;
> +}
> +
> +static int valid_log_type(int type)
> +{
> +       return type == LOG_EXEC_IDX || type == LOG_HISTORY_IDX;
> +}
> +
> +static inline int valid_log_revid(int id)
> +{
> +       return id == REVID_1 || id == REVID_2;
> +}
> +
> +static void help(void)
> +{
> +       fprintf(stderr,
> +               "usage: %s [OPTIONS]\n"
> +               " code injection:\n"
> +               "  -l, --load\n"
> +               "  -s, --stage\n"
> +               "  -a, --activate\n"
> +               "  -u, --update [stage and activate]\n"
> +               "  -q, --query\n"
> +               "  -d, --revid update\n"
> +               " telemetry:\n"
> +               "  -G, --getloginfo\n"
> +               "  -T, --type(0:execution, 1:history)\n"
> +               "  -L, --level(0, 1, 2, 4)\n"
> +               "  -R, --read\n"
> +               "  -D, --revid log\n",
> +               progname);
> +}
> +
> +char *option_string = "l:sauqd:GT:L:RD:h";
> +static struct option long_options[] = {
> +       {"load", required_argument, 0, 'l'},
> +       {"stage", no_argument, 0, 's'},
> +       {"activate", no_argument, 0, 'a'},
> +       {"update", no_argument, 0, 'u'},
> +       {"query", no_argument, 0, 'q'},
> +       {"getloginfo", no_argument, 0, 'G'},
> +       {"type", required_argument, 0, 'T'},
> +       {"level", required_argument, 0, 'L'},
> +       {"read", no_argument, 0, 'R'},
> +       {"setrev", required_argument, 0, 'd'},
> +       {"setrevlog", required_argument, 0, 'D'},
> +       {"help", no_argument, 0, 'h'},
> +       {}
> +};
> +
> +static void parse_options(int argc, char **argv)
> +{
> +       int option_index = 0;
> +       char *pathname;
> +       int opt;
> +
> +       pathname = strdup(argv[0]);
> +       progname = basename(pathname);
> +
> +       while ((opt = getopt_long_only(argc, argv, option_string,
> +                                      long_options, &option_index)) != -1) {
> +               switch (opt) {
> +               case 'l':
> +                       capsule_name = optarg;
> +                       break;
> +               case 's':
> +                       action = 1;
> +                       break;
> +               case 'a':
> +                       action = 2;
> +                       break;
> +               case 'u':
> +                       action = 3;
> +                       break;
> +               case 'q':
> +                       query_cap = 1;
> +                       break;
> +               case 'G':
> +                       log_getinfo = 1;
> +                       break;
> +               case 'T':
> +                       log_type = atoi(optarg);
> +                       set_log_type = 1;
> +                       break;
> +               case 'L':
> +                       log_level = atoi(optarg);
> +                       set_log_level = 1;
> +                       break;
> +               case 'R':
> +                       log_read = 1;
> +                       break;
> +               case 'd':
> +                       revid = atoi(optarg);
> +                       set_revid = 1;
> +                       break;
> +               case 'D':
> +                       log_revid = atoi(optarg);
> +                       set_log_revid = 1;
> +                       break;
> +               case 'h':
> +                       help();
> +                       exit(0);
> +               default:
> +                       break;
> +               }
> +       }
> +}
> +
> +void print_cap(struct pfru_update_cap_info *cap)
> +{
> +       char *uuid;
> +
> +       uuid = malloc(37);
> +       if (!uuid) {
> +               perror("Can not allocate uuid buffer\n");
> +               exit(1);
> +       }
> +
> +       uuid_unparse(cap->code_type, uuid);
> +       printf("code injection image type:%s\n", uuid);
> +       printf("fw_version:%d\n", cap->fw_version);
> +       printf("code_rt_version:%d\n", cap->code_rt_version);
> +
> +       uuid_unparse(cap->drv_type, uuid);
> +       printf("driver update image type:%s\n", uuid);
> +       printf("drv_rt_version:%d\n", cap->drv_rt_version);
> +       printf("drv_svn:%d\n", cap->drv_svn);
> +
> +       uuid_unparse(cap->platform_id, uuid);
> +       printf("platform id:%s\n", uuid);
> +       uuid_unparse(cap->oem_id, uuid);
> +       printf("oem id:%s\n", uuid);
> +       printf("oem information length:%d\n", cap->oem_info_len);
> +
> +       free(uuid);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +       int fd_update, fd_update_log, fd_capsule;
> +       struct pfru_log_data_info data_info;
> +       struct pfru_log_info info;
> +       struct pfru_update_cap_info cap;
> +       void *addr_map_capsule;
> +       struct stat st;
> +       char *log_buf;
> +       int ret = 0;
> +
> +       if (getuid() != 0) {
> +               printf("Please run the tool as root - Exiting.\n");
> +               return 1;
> +       }
> +
> +       parse_options(argc, argv);
> +
> +       fd_update = open("/dev/acpi_pfru0", O_RDWR);
> +       if (fd_update < 0) {
> +               printf("PFRU device not supported - Quit...\n");
> +               return 1;
> +       }
> +
> +       fd_update_log = open("/dev/acpi_pfru_telemetry0", O_RDWR);
> +       if (fd_update_log < 0) {
> +               printf("PFRU telemetry device not supported - Quit...\n");
> +               return 1;
> +       }
> +
> +       if (query_cap) {
> +               ret = ioctl(fd_update, PFRU_IOC_QUERY_CAP, &cap);
> +               if (ret)
> +                       perror("Query Update Capability info failed.");
> +               else
> +                       print_cap(&cap);
> +
> +               close(fd_update);
> +               close(fd_update_log);
> +
> +               return ret;
> +       }
> +
> +       if (log_getinfo) {
> +               ret = ioctl(fd_update_log, PFRU_LOG_IOC_GET_DATA_INFO, &data_info);
> +               if (ret) {
> +                       perror("Get telemetry data info failed.");
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               ret = ioctl(fd_update_log, PFRU_LOG_IOC_GET_INFO, &info);
> +               if (ret) {
> +                       perror("Get telemetry info failed.");
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               printf("log_level:%d\n", info.log_level);
> +               printf("log_type:%d\n", info.log_type);
> +               printf("log_revid:%d\n", info.log_revid);
> +               printf("max_data_size:%d\n", data_info.max_data_size);
> +               printf("chunk1_size:%d\n", data_info.chunk1_size);
> +               printf("chunk2_size:%d\n", data_info.chunk2_size);
> +               printf("rollover_cnt:%d\n", data_info.rollover_cnt);
> +               printf("reset_cnt:%d\n", data_info.reset_cnt);
> +
> +               return 0;
> +       }
> +
> +       info.log_level = -1;
> +       info.log_type = -1;
> +       info.log_revid = -1;
> +
> +       if (set_log_level) {
> +               if (!valid_log_level(log_level)) {
> +                       printf("Invalid log level %d\n",
> +                              log_level);
> +               } else {
> +                       info.log_level = log_level;
> +               }
> +       }
> +
> +       if (set_log_type) {
> +               if (!valid_log_type(log_type)) {
> +                       printf("Invalid log type %d\n",
> +                              log_type);
> +               } else {
> +                       info.log_type = log_type;
> +               }
> +       }
> +
> +       if (set_log_revid) {
> +               if (!valid_log_revid(log_revid)) {
> +                       printf("Invalid log revid %d, unchanged.\n",
> +                              log_revid);
> +               } else {
> +                       info.log_revid = log_revid;
> +               }
> +       }
> +
> +       ret = ioctl(fd_update_log, PFRU_LOG_IOC_SET_INFO, &info);
> +       if (ret) {
> +               perror("Log information set failed.(log_level, log_type, log_revid)");
> +               close(fd_update);
> +               close(fd_update_log);
> +
> +               return 1;
> +       }
> +
> +       if (set_revid) {
> +               ret = ioctl(fd_update, PFRU_IOC_SET_REV, &revid);
> +               if (ret) {
> +                       perror("pfru update revid set failed");
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               printf("pfru update revid set to %d\n", revid);
> +       }
> +
> +       if (capsule_name) {
> +               fd_capsule = open(capsule_name, O_RDONLY);
> +               if (fd_capsule < 0) {
> +                       perror("Can not open capsule file...");
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               if (fstat(fd_capsule, &st) < 0) {
> +                       perror("Can not fstat capsule file...");
> +                       close(fd_capsule);
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               addr_map_capsule = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED,
> +                                       fd_capsule, 0);
> +               if (addr_map_capsule == MAP_FAILED) {
> +                       perror("Failed to mmap capsule file.");
> +                       close(fd_capsule);
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               ret = write(fd_update, (char *)addr_map_capsule, st.st_size);
> +               printf("Load %d bytes of capsule file into the system\n",
> +                      ret);
> +
> +               if (ret == -1) {
> +                       perror("Failed to load capsule file");
> +                       close(fd_capsule);
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               munmap(addr_map_capsule, st.st_size);
> +               close(fd_capsule);
> +               printf("Load done.\n");
> +       }
> +
> +       if (action) {
> +               if (action == 1) {
> +                       ret = ioctl(fd_update, PFRU_IOC_STAGE, NULL);
> +               } else if (action == 2) {
> +                       ret = ioctl(fd_update, PFRU_IOC_ACTIVATE, NULL);
> +               } else if (action == 3) {
> +                       ret = ioctl(fd_update, PFRU_IOC_STAGE_ACTIVATE, NULL);
> +               } else {
> +                       close(fd_update);
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +               printf("Update finished, return %d\n", ret);
> +       }
> +
> +       close(fd_update);
> +
> +       if (log_read) {
> +               void *p_mmap;
> +               int max_data_sz;
> +
> +               ret = ioctl(fd_update_log, PFRU_LOG_IOC_GET_DATA_INFO, &data_info);
> +               if (ret) {
> +                       perror("Get telemetry data info failed.");
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               max_data_sz = data_info.max_data_size;
> +               if (!max_data_sz) {
> +                       printf("No telemetry data available.\n");
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               log_buf = malloc(max_data_sz + 1);
> +               if (!log_buf) {
> +                       perror("log_buf allocate failed.");
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               p_mmap = mmap(NULL, max_data_sz, PROT_READ, MAP_SHARED, fd_update_log, 0);
> +               if (p_mmap == MAP_FAILED) {
> +                       perror("mmap error.");
> +                       close(fd_update_log);
> +
> +                       return 1;
> +               }
> +
> +               memcpy(log_buf, p_mmap, max_data_sz);
> +               log_buf[max_data_sz] = '\0';
> +               printf("%s\n", log_buf);
> +               free(log_buf);
> +
> +               munmap(p_mmap, max_data_sz);
> +       }
> +
> +       close(fd_update_log);
> +
> +       return 0;
> +}
> --

Please adjust the patch for the build fixes sent separately.

Otherwise it is fine with me.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ