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