From c9607839e6806ae3cfcd37c545728b95f48c51dd Mon Sep 17 00:00:00 2001 From: Lukasz Stanislawski Date: Thu, 26 Jul 2018 12:25:28 +0200 Subject: [PATCH] procfs: improve parsing of stat file In rare situation when process could have malicious name containing some tricky characters like whitespaces and numbers - the parsing result may be wrong. This patch fixes this issue by loading whole stat file into memory and then proceed with parsing. Change-Id: Iede6e0b6d1362a56449e1a53a0348f6cd7b4f768 --- src/procfs.c | 70 ++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/src/procfs.c b/src/procfs.c index 6ea8ebb..7c81e53 100644 --- a/src/procfs.c +++ b/src/procfs.c @@ -186,44 +186,73 @@ int procfs_read_process_smaps(int pid, struct procfs_process_smaps *usage) return 0; } +static int read_file(const char *filename, char *buf, size_t buf_size) +{ + FILE *fp = fopen(filename, "r"); + if (!fp) return -1; + + size_t read = fread(buf, 1, buf_size, fp); + if (read <= 0) { + fclose(fp); + return -1; + } + buf[read-1] = '\0'; + fclose(fp); + return read; +} + int procfs_read_process_stat(int pid, struct procfs_process_stat *usage) { ON_NULL_RETURN_VAL(usage, -1); ON_TRUE_RETURN_VAL(pid <= 0, -1); char statpath[64]; + char buf[1024]; unsigned long long utime, stime; unsigned long rss; + int read; snprintf(statpath, sizeof(statpath), PIDSTAT_FILEPATH, pid); - FILE *stat_fp = fopen(statpath, "r"); - if (!stat_fp) { - ERR("failed to open %s", statpath); + if ((read = read_file(statpath, buf, sizeof(buf))) <= 0) { return -1; } - if (fscanf(stat_fp, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s") < 0) { - ERR("reading pid stat file failed"); - fclose(stat_fp); + if (read == sizeof(buf)) { return -1; } - if (fscanf(stat_fp, "%llu %llu", &utime, &stime) != 2) { + char *name_end = strrchr(buf, ')'); + if (!name_end) return -1; + + name_end += 1; + + if (sscanf(name_end, + "%*c " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%llu " + "%llu " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%*s " + "%ld" + , &utime, &stime, &rss) != 3) { ERR("reading pid stat file failed"); - fclose(stat_fp); - return -1; - } - - if (fscanf(stat_fp, "%*s %*s %*s %*s %*s %*s %*s %*s") < 0) { - ERR("reading pid stat file failed"); - fclose(stat_fp); - return -1; - } - - if (fscanf(stat_fp, "%ld", &rss) != 1) { - ERR("reading pid stat file failed"); - fclose(stat_fp); return -1; } @@ -231,7 +260,6 @@ int procfs_read_process_stat(int pid, struct procfs_process_stat *usage) usage->stime = stime; usage->rss = rss; - fclose(stat_fp); return 0; } -- 2.7.4