From 58ecf1f363c35f452f5d00697620e520029bef83 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Wed, 27 Jun 2018 19:32:31 +0200 Subject: [PATCH] mon_procd: fix parsing of /proc//stat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The output of /proc//stat will show the process name in parentheses. The parsing code in read_stat() tries to filter out the parentheses, which will go wrong when the process name itself also contains parentheses, e.g. in an output like this: "2421 ((sd-pam)) S 2420 2420 2420 ..." In this case, the first closing parentheses will be taken as end marker, and the sscanf() on the remaining string will silently fail, leaving its values in uninitialized state and producing wrong data. Fix this by using strrchr() instead of strchr() to find the last closing parentheses. Also add return value checking for sscanf() and initialize the values to 0. Signed-off-by: Gerald Schaefer Signed-off-by: Jan Höppner --- CHANGELOG.md | 1 + mon_tools/mon_procd.c | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a62241e..291132a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Release history for s390-tools (MIT version) Changes of existing tools: Bug Fixes: + - mon_procd: fix parsing of /proc//stat * __v2.5.0 (2018-06-08)__ diff --git a/mon_tools/mon_procd.c b/mon_tools/mon_procd.c index d02b88d3..e242cc29 100644 --- a/mon_tools/mon_procd.c +++ b/mon_tools/mon_procd.c @@ -594,17 +594,18 @@ static void cal_task_pcpu(struct task_t *task, const unsigned long long tics) */ static int read_stat(struct task_t *task) { - int ppid, tty, proc; - unsigned long flags, pri, nice; - unsigned long long maj_flt, utime, stime, cutime, cstime; + unsigned long long maj_flt = 0, utime = 0, stime = 0, cutime = 0, + cstime = 0; + unsigned long flags = 0, pri = 0, nice = 0; char *cmd_start, *cmd_end, *cmdlenp, *cmdp; + int ppid = 0, tty = 0, proc = 0, rc; snprintf(fname, sizeof(fname), "/proc/%u/stat", task->pid); if (read_file(fname, buf, sizeof(buf) - 1) == -1) return 0; cmd_start = strchr(buf, '(') + 1; - cmd_end = strchr(cmd_start, ')'); + cmd_end = strrchr(cmd_start, ')'); name_lens.cmd_len = cmd_end - cmd_start; cmdlenp = mon_record + sizeof(struct monwrite_hdr); cmdlenp += sizeof(struct procd_hdr); @@ -625,7 +626,7 @@ static int read_stat(struct task_t *task) memcpy(cmdlenp, &name_lens.cmd_len, sizeof(__u16)); cmd_end += 2; - sscanf(cmd_end, + rc = sscanf(cmd_end, "%c %d %*d %*d %d %*d " "%lu %*s %*s %Lu %*s " "%Lu %Lu %Lu %Lu " @@ -642,6 +643,8 @@ static int read_stat(struct task_t *task) &utime, &stime, &cutime, &cstime, &pri, &nice, &proc); + if (rc != 12) + syslog(LOG_ERR, "bad data in %s \n", fname); task->ppid = (__u32)ppid; task->tty = (__u16)tty; task->flags = (__u32)flags;