The functions for viewing log files in iprconfig used a number of system() calls
to display information to the user. This commit rewrites the log viewing system
with more secure fork()/exec() calls. The log info is displayed to the user
through the "less" pager, with the environment variable LESSSECURE set to 1 to
prevent arbitrary command execution during log inspection.

Signed-off-by: Heitor Ricardo Alves de Siqueira <hal...@linux.vnet.ibm.com>
---
 iprconfig.c | 438 +++++++++++++++++++++++++++++++-----------------------------
 iprlib.c    |  18 +++
 iprlib.h    |   2 +
 3 files changed, 248 insertions(+), 210 deletions(-)

diff --git a/iprconfig.c b/iprconfig.c
index 65db394c84d7..c71a946f03d0 100644
--- a/iprconfig.c
+++ b/iprconfig.c
@@ -11917,51 +11917,61 @@ int log_menu(i_container *i_con)
  * Returns:
  *   1 if no status / 65 on failure
  **/
-
 int ibm_storage_log_tail(i_container *i_con)
 {
-       char cmnd[MAX_CMD_LENGTH];
-       int rc, len;
+       int rc, pid, status;
        int log_fd;
        char *logfile;
 
        logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
        log_fd = mkstemp(logfile);
+       if (log_fd < 0) {
+               closelog();
+               openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
+               syslog(LOG_ERR, "Could not create temp log file: %m\n");
+               closelog();
+               openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER);
+               return 65;
+       }
 
        def_prog_mode();
+       endwin();
 
-       if (log_fd == -1) {
-               len = sprintf(cmnd, "cd %s; zcat -f messages", log_root_dir);
-
-               len += sprintf(cmnd + len," | grep ipr | ");
-               len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: 
ipr//g\" | ");
-               len += sprintf(cmnd + len, "sed \"s/ localhost kernel: ipr//g\" 
| ");
-               len += sprintf(cmnd + len, "sed \"s/ kernel: ipr//g\" | ");
-               len += sprintf(cmnd + len, "sed \"s/\\^M//g\" | ");
-               len += sprintf(cmnd + len, FAILSAFE_EDITOR);
-               closelog();
-               openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
-               syslog(LOG_ERR, "Error encountered concatenating log 
files...\n");
-               syslog(LOG_ERR, "Using failsafe editor...\n");
-               closelog();
-               openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER);
-               sleep(3);
+       /* sed log file for relevant information */
+       pid = fork();
+       if (pid == 0) {
+               char *dot;
+               char host[256];
+               char hostname_regex[256];
+               char logsource[256];
+               char *args[] = {
+                       "/usr/bin/sed",
+                       "-e", "/ipr/!d",
+                       "-e", "s/\\^M//g",
+                       "-e", hostname_regex,
+                       logsource, NULL
+               };
+
+               /* build hostname regex and logsource */
+               gethostname(host, sizeof(host));
+               dot = strchr(host, '.');
+               if (dot != NULL)
+                       *dot = '\0';
+               snprintf(hostname_regex, sizeof(hostname_regex),
+                        "s/\\(%s \\|localhost \\)\\?kernel: ipr//g", host);
+               snprintf(logsource, sizeof(logsource),
+                        "%s/messages", log_root_dir);
+
+               /* bind stdout to tmp file for correct output */
+               dup2(log_fd, STDOUT_FILENO);
+               execv("/usr/bin/sed", args);
+               _exit(errno);
        } else {
-               len = sprintf(cmnd,"cd %s; zcat -f messages | grep ipr |", 
log_root_dir);
-               len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: 
ipr//g\"");
-               len += sprintf(cmnd + len, " | sed \"s/ localhost kernel: 
ipr//g\"");
-               len += sprintf(cmnd + len, " | sed \"s/ kernel: ipr//g\"");
-               len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" ");
-               len += sprintf(cmnd + len, ">> %s", logfile);
-               system(cmnd);
-
-               sprintf(cmnd, "%s %s", editor, logfile);
+               waitpid(pid, &status, 0);
        }
 
-       rc = system(cmnd);
-
-       if (log_fd != -1)
-               close(log_fd);
+       close(log_fd);
+       rc = invoke_pager(logfile);
 
        if ((rc != 0) && (rc != 127)) {
                /* "Editor returned %d. Try setting the default editor" */
@@ -12022,27 +12032,18 @@ static int compare_log_file(const struct dirent 
**first_dir, const struct dirent
 }
 
 /**
- * ibm_storage_log -
- * @i_con:             i_container struct
+ * copy_log_files -
+ * @out_fd:            output file descriptor
  *
  * Returns:
- *   0 if success / non-zero on failure FIXME
+ *   0 if success / non-zero on failure
  **/
-int ibm_storage_log(i_container *i_con)
+static int copy_log_files(int out_fd)
 {
-       char cmnd[MAX_CMD_LENGTH];
-       int i;
+       int i, pid, status;
        struct dirent **log_files;
        struct dirent **dirent;
        int num_dir_entries;
-       int rc, len;
-       int log_fd;
-       char *logfile;
-
-       logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
-       log_fd = mkstemp(logfile);
-
-       def_prog_mode();
 
        num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, 
compare_log_file);
        if (num_dir_entries < 0) {
@@ -12053,54 +12053,104 @@ int ibm_storage_log(i_container *i_con)
        if (num_dir_entries)
                dirent = log_files;
 
-       if (log_fd == -1) {
-               len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir);
-
-               /* Probably have a read-only root file system */
-               for (i = 0; i < num_dir_entries; i++) {
-                       len += sprintf(cmnd + len, "%s ", (*dirent)->d_name);
+       pid = fork();
+       if (pid == 0) {
+               char logsource[MAX_CMD_LENGTH];
+               char **args = malloc(sizeof(char*) * (num_dir_entries+3));
+               char *zcat_path = "/usr/bin/zcat";
+               char *zcat_flag = "-f";
+               int arg_size;
+
+               args[0] = zcat_path;
+               args[1] = zcat_flag;
+               args[num_dir_entries+2] = NULL;
+
+               for (i = 2; i < num_dir_entries +2; ++i) {
+                       arg_size = strlen(log_root_dir) +
+                                  strlen((*dirent)->d_name) + 2;
+                       args[i] = malloc(arg_size);
+                       snprintf(args[i], arg_size, "%s/%s",
+                                log_root_dir, (*dirent)->d_name);
                        dirent++;
                }
 
-               len += sprintf(cmnd + len," | grep ipr-err | ");
-               len += sprintf(cmnd + len, "sed \"s/ `hostname -s` kernel: 
ipr//g\" | ");
-               len += sprintf(cmnd + len, "sed \"s/ localhost kernel: ipr//g\" 
| ");
-               len += sprintf(cmnd + len, "sed \"s/ kernel: ipr//g\" | ");
-               len += sprintf(cmnd + len, "sed \"s/\\^M//g\" | ");
-               len += sprintf(cmnd + len, FAILSAFE_EDITOR);
-               closelog();
-               openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
-               syslog(LOG_ERR, "Error encountered concatenating log 
files...\n");
-               syslog(LOG_ERR, "Using failsafe editor...\n");
-               closelog();
-               openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER);
-               sleep(3);
+               /* bind out_fd to sdtout so zcat prints to file */
+               dup2(out_fd, STDOUT_FILENO);
+               execv("/usr/bin/zcat", args);
+               _exit(errno);
        } else {
-               for (i = 0; i < num_dir_entries; i++) {
-                       len = sprintf(cmnd,"cd %s; zcat -f %s | grep ipr |", 
log_root_dir, (*dirent)->d_name);
-                       len += sprintf(cmnd + len, "sed \"s/ `hostname -s` 
kernel: ipr//g\"");
-                       len += sprintf(cmnd + len, " | sed \"s/ localhost 
kernel: ipr//g\"");
-                       len += sprintf(cmnd + len, " | sed \"s/ kernel: 
ipr//g\"");
-                       len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" ");
-                       len += sprintf(cmnd + len, ">> %s", logfile);
-                       system(cmnd);
-                       dirent++;
-               }
-
-               sprintf(cmnd, "%s %s", editor, logfile);
+               waitpid(pid, &status, 0);
        }
 
-       rc = system(cmnd);
-
-       if (log_fd != -1)
-               close(log_fd);
-
        if (num_dir_entries) {
                while (num_dir_entries--)
                        free(log_files[num_dir_entries]);
                free(log_files);
        }
 
+       return WEXITSTATUS(status);
+}
+
+/**
+ * ibm_storage_log -
+ * @i_con:             i_container struct
+ *
+ * Returns:
+ *   0 if success / non-zero on failure FIXME
+ **/
+int ibm_storage_log(i_container *i_con)
+{
+       int rc, i, pid, status;
+       int log_fd;
+       char *logfile;
+
+       logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
+       log_fd = mkstemp(logfile);
+       if (log_fd < 0) {
+               closelog();
+               openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
+               syslog(LOG_ERR, "Could not create temp log file: %m\n");
+               closelog();
+               openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER);
+               return 65;
+       }
+
+       def_prog_mode();
+       endwin();
+
+       /* copy logs to tmp file */
+       copy_log_files(log_fd);
+       close(log_fd);
+
+       /* sed tmp file for relevant information */
+       pid = fork();
+       if (pid == 0) {
+               char *dot;
+               char host[256];
+               char hostname_regex[256];
+               char *args[] = {
+                       "/usr/bin/sed", "-i",
+                       "-e", "/ipr/!d",
+                       "-e", "s/\\^M//g",
+                       "-e", hostname_regex,
+                       logfile, NULL
+               };
+
+               /* build hostname regex */
+               gethostname(host, sizeof(host));
+               dot = strchr(host, '.');
+               if (dot != NULL)
+                       *dot = '\0';
+               snprintf(hostname_regex, sizeof(hostname_regex),
+                        "s/\\(%s \\|localhost \\)\\?kernel: ipr//g", host);
+               execv("/usr/bin/sed", args);
+               _exit(errno);
+       } else {
+               waitpid(pid, &status, 0);
+       }
+
+       rc = invoke_pager(logfile);
+
        if ((rc != 0) && (rc != 127)) {
                /* "Editor returned %d. Try setting the default editor" */
                s_status.num = rc;
@@ -12119,69 +12169,44 @@ int ibm_storage_log(i_container *i_con)
  **/
 int kernel_log(i_container *i_con)
 {
-       char cmnd[MAX_CMD_LENGTH];
-       int rc, i;
-       struct dirent **log_files;
-       struct dirent **dirent;
-       int num_dir_entries;
-       int len;
+       int rc, pid, status;
        int log_fd;
        char *logfile;
 
        logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
        log_fd = mkstemp(logfile);
-
-       def_prog_mode();
-
-       num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, 
compare_log_file);
-       if (num_dir_entries < 0) {
-               s_status.num = 75;
-               return 75;
+       if (log_fd < 0) {
+               closelog();
+               openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
+               syslog(LOG_ERR, "Could not create temp log file: %m\n");
+               closelog();
+               openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER);
+               return 65;
        }
 
-       if (num_dir_entries)
-               dirent = log_files;
-
-       if (log_fd == -1) {
-               /* Probably have a read-only root file system */
-               len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir);
+       def_prog_mode();
+       endwin();
 
-               /* Probably have a read-only root file system */
-               for (i = 0; i < num_dir_entries; i++) {
-                       len += sprintf(cmnd + len, "%s ", (*dirent)->d_name);
-                       dirent++;
-               }
+       /* copy logs to tmp file */
+       copy_log_files(log_fd);
+       close(log_fd);
 
-               len += sprintf(cmnd + len, " | sed \"s/\\^M//g\" ");
-               len += sprintf(cmnd + len, "| %s", FAILSAFE_EDITOR);
-               closelog();
-               openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
-               syslog(LOG_ERR, "Error encountered concatenating log 
files...\n");
-               syslog(LOG_ERR, "Using failsafe editor...\n");
-               openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER);
-               sleep(3);
+       /* remove unwanted ^M */
+       pid = fork();
+       if (pid == 0) {
+               char *args[] = {
+                       "/usr/bin/sed", "-i",
+                       "-e", "s/\\^M//g",
+                       logfile, NULL
+               };
+
+               execv("/usr/bin/sed", args);
+               _exit(errno);
        } else {
-               for (i = 0; i < num_dir_entries; i++) {
-                       sprintf(cmnd,
-                               "cd %s; zcat -f %s | sed \"s/\\^M//g\" >> %s",
-                               log_root_dir, (*dirent)->d_name, logfile);
-                       system(cmnd);
-                       dirent++;
-               }
-
-               sprintf(cmnd, "%s %s", editor, logfile);
+               waitpid(pid, &status, 0);
        }
 
-       rc = system(cmnd);
-
-       if (log_fd != -1)
-               close(log_fd);
-
-       if (num_dir_entries > 0) {
-               while (num_dir_entries--)
-                       free(log_files[num_dir_entries]);
-               free(log_files);
-       }
+       rc = invoke_pager(logfile);
 
        if ((rc != 0) && (rc != 127))   {
                /* "Editor returned %d. Try setting the default editor" */
@@ -12202,67 +12227,56 @@ int kernel_log(i_container *i_con)
  **/
 int iprconfig_log(i_container *i_con)
 {
-       char cmnd[MAX_CMD_LENGTH];
-       int rc, i;
-       struct dirent **log_files;
-       struct dirent **dirent;
-       int num_dir_entries;
-       int len;
+       int rc, i, pid, status;
        int log_fd;
        char *logfile;
 
        logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
        log_fd = mkstemp(logfile);
-
-       def_prog_mode();
-
-       num_dir_entries = scandir(log_root_dir, &log_files, select_log_file, 
compare_log_file);
-       if (num_dir_entries < 0) {
-               s_status.num = 75;
-               return 75;
+       if (log_fd < 0) {
+               closelog();
+               openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
+               syslog(LOG_ERR, "Could not create temp log file: %m\n");
+               closelog();
+               openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER);
+               return 65;
        }
 
-       if (num_dir_entries)
-               dirent = log_files;
-
-       if (log_fd == -1) {
-               len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir);
+       def_prog_mode();
+       endwin();
 
-               /* Probably have a read-only root file system */
-               for (i = 0; i < num_dir_entries; i++) {
-                       len += sprintf(cmnd + len, "%s ", (*dirent)->d_name);
-                       dirent++;
-               }
+       /* copy logs to tmp file */
+       copy_log_files(log_fd);
+       close(log_fd);
 
-               len += sprintf(cmnd + len," | grep iprconfig | ");
-               len += sprintf(cmnd + len, FAILSAFE_EDITOR);
-               closelog();
-               openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
-               syslog(LOG_ERR, "Error encountered concatenating log 
files...\n");
-               syslog(LOG_ERR, "Using failsafe editor...\n");
-               openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER);
-               sleep(3);
+       /* sed tmp file for relevant information */
+       pid = fork();
+       if (pid == 0) {
+               char *dot;
+               char host[256];
+               char hostname_regex[256];
+               char *args[] = {
+                       "/usr/bin/sed", "-i",
+                       "-e", "/iprconfig/!d",
+                       "-e", "s/\\^M//g",
+                       "-e", hostname_regex,
+                       logfile, NULL
+               };
+
+               /* build hostname regex */
+               gethostname(host, sizeof(host));
+               dot = strchr(host, '.');
+               if (dot != NULL)
+                       *dot = '\0';
+               snprintf(hostname_regex, sizeof(hostname_regex),
+                        "s/\\(%s \\|localhost \\)\\?kernel: ipr//g", host);
+               execv("/usr/bin/sed", args);
+               _exit(errno);
        } else {
-               for (i = 0; i < num_dir_entries; i++) {
-                       len = sprintf(cmnd,"cd %s; zcat -f %s | grep iprconfig 
", log_root_dir, (*dirent)->d_name);
-                       len += sprintf(cmnd + len, ">> %s", logfile);
-                       system(cmnd);
-                       dirent++;
-               }
-
-               sprintf(cmnd, "%s %s", editor, logfile);
+               waitpid(pid, &status, 0);
        }
 
-       rc = system(cmnd);
-
-       if (log_fd != -1)
-               close(log_fd);
-
-       if (num_dir_entries) {
-               while (num_dir_entries--)
-                       free(log_files[num_dir_entries]);
-               free(log_files);
-       }
+       rc = invoke_pager(logfile);
 
        if ((rc != 0) && (rc != 127))   {
                /* "Editor returned %d. Try setting the default editor" */
@@ -12462,50 +12476,54 @@ int restore_log_defaults(i_container *i_con)
  **/
 int ibm_boot_log(i_container *i_con)
 {
-       char cmnd[MAX_CMD_LENGTH];
-       int rc;
-       int len;
+       int rc, pid, status;
        struct stat file_stat;
        int log_fd;
        char *logfile;
+       char logsource[256];
 
 
-       sprintf(cmnd,"%s/boot.msg",log_root_dir);
-       rc = stat(cmnd, &file_stat);
+       snprintf(logsource, sizeof(logsource), "%s/boot.msg", log_root_dir);
+       rc = stat(logsource, &file_stat);
        if (rc)
                return 2; /* "Invalid option specified" */
 
        logfile = strdup(_PATH_TMP"iprerror-XXXXXX");
        log_fd = mkstemp(logfile);
+       if (log_fd < 0) {
+               closelog();
+               openlog(tool_name, LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
+               syslog(LOG_ERR, "Could not create temp log file: %m\n");
+               closelog();
+               openlog(tool_name, LOG_PID | LOG_CONS, LOG_USER);
+               return 65;
+       }
 
        def_prog_mode();
+       endwin();
 
-       if (log_fd == -1) {
-               len = sprintf(cmnd, "cd %s; zcat -f ", log_root_dir);
+       /* sed log file for relevant information */
+       pid = fork();
+       if (pid == 0) {
+               char *args[] = {
+                       "/usr/bin/sed",
+                       "-e", "/ipr/!d",
+                       "-e", "s/<[0-9]>ipr-err: //g",
+                       "-e", "s/<[0-9]>ipr: //g",
+                       logsource, NULL
+               };
+
+               /* bind stdout to tmp file for correct output */
+               dup2(log_fd, STDOUT_FILENO);
+               execv("/usr/bin/sed", args);
+               _exit(errno);
 
-               /* Probably have a read-only root file system */
-               len += sprintf(cmnd + len, "boot.msg");
-               len += sprintf(cmnd + len," | grep ipr |");
-               len += sprintf(cmnd + len, FAILSAFE_EDITOR);
-               closelog();
-               openlog("iprconfig", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
-               syslog(LOG_ERR, "Error encountered concatenating log 
files...\n");
-               syslog(LOG_ERR, "Using failsafe editor...\n");
-               closelog();
-               openlog("iprconfig", LOG_PID | LOG_CONS, LOG_USER);
-               sleep(3);
        } else {
-               len = sprintf(cmnd,"cd %s; zcat -f boot.msg | grep ipr  | "
-                             "sed 's/<[0-9]>ipr-err: //g' | sed 's/<[0-9]>ipr: 
//g'",
-                             log_root_dir);
-               len += sprintf(cmnd + len, ">> %s", logfile);
-               system(cmnd);
-               sprintf(cmnd, "%s %s", editor, logfile);
+               waitpid(pid, &status, 0);
        }
-       rc = system(cmnd);
 
-       if (log_fd != -1)
-               close(log_fd);
+       close(log_fd);
+       rc = invoke_pager(logfile);
 
        if ((rc != 0) && (rc != 127)) {
                s_status.num = rc;
diff --git a/iprlib.c b/iprlib.c
index 6e5a487da3c6..5bb62bbe1692 100644
--- a/iprlib.c
+++ b/iprlib.c
@@ -9986,3 +9986,21 @@ int ipr_query_io_dev_port(struct ipr_dev *dev, struct 
ipr_query_io_port *io_port
        return rc;
 }
 
+int invoke_pager(char *filename)
+{
+       int pid, status;
+       char *pager = "/usr/bin/less";
+       char *argv[] = {pager, "-c", filename, NULL};
+
+       pid = fork();
+       if (pid == 0) {
+               /* disable insecure pager features */
+               putenv("LESSSECURE=1");
+               execv(pager, argv);
+               _exit(errno);
+       } else {
+               waitpid(pid, &status, 0);
+       }
+
+       return WEXITSTATUS(status);
+}
diff --git a/iprlib.h b/iprlib.h
index cf6bf7989562..3da0e98f4fbc 100644
--- a/iprlib.h
+++ b/iprlib.h
@@ -38,6 +38,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
 #include <ctype.h>
 #include <syslog.h>
 #include <term.h>
@@ -2772,6 +2773,7 @@ u32 get_ioa_ucode_version(char *);
 int ipr_improper_device_type(struct ipr_dev *);
 int ipr_get_fw_version(struct ipr_dev *, u8 release_level[4]);
 int ipr_get_live_dump(struct ipr_ioa *);
+int invoke_pager(char *filename);
 
 static inline u32 ipr_get_dev_res_handle(struct ipr_ioa *ioa, struct 
ipr_dev_record *dev_rcd)
 {
-- 
2.4.3


------------------------------------------------------------------------------
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741911&iu=/4140
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to