procfs: improve parsing of stat file 73/185173/1
authorLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 26 Jul 2018 10:25:28 +0000 (12:25 +0200)
committerLukasz Stanislawski <l.stanislaws@samsung.com>
Thu, 26 Jul 2018 12:24:13 +0000 (14:24 +0200)
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

index 6ea8ebb..7c81e53 100644 (file)
@@ -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;
 }