diff options
author | 2018-12-17 11:23:15 +0100 | |
---|---|---|
committer | 2018-12-18 15:03:05 +0100 | |
commit | 2a7797e964e5b6a0f305b00073e2b06a195d0b15 (patch) | |
tree | cde681201fc40f1824dea692d8feced13343a83a | |
parent | tree-wide: port some code over to safe_fgetc() (diff) | |
download | systemd-2a7797e964e5b6a0f305b00073e2b06a195d0b15.tar.gz systemd-2a7797e964e5b6a0f305b00073e2b06a195d0b15.tar.bz2 systemd-2a7797e964e5b6a0f305b00073e2b06a195d0b15.zip |
process-util: make get_process_environ() safer
Let's add a size limit, and let's use safe_fgetc().
-rw-r--r-- | src/basic/process-util.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 5b700df33..ebf613b9d 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -600,12 +600,14 @@ int get_process_root(pid_t pid, char **root) { return get_process_link_contents(p, root); } +#define ENVIRONMENT_BLOCK_MAX (5U*1024U*1024U) + int get_process_environ(pid_t pid, char **env) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *outcome = NULL; - int c; - const char *p; size_t allocated = 0, sz = 0; + const char *p; + int r; assert(pid >= 0); assert(env); @@ -621,23 +623,28 @@ int get_process_environ(pid_t pid, char **env) { (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - while ((c = fgetc(f)) != EOF) { + for (;;) { + char c; + + if (sz >= ENVIRONMENT_BLOCK_MAX) + return -ENOBUFS; + if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) return -ENOMEM; + r = safe_fgetc(f, &c); + if (r < 0) + return r; + if (r == 0) + break; + if (c == '\0') outcome[sz++] = '\n'; else sz += cescape_char(c, outcome + sz); } - if (!outcome) { - outcome = strdup(""); - if (!outcome) - return -ENOMEM; - } else - outcome[sz] = '\0'; - + outcome[sz] = '\0'; *env = TAKE_PTR(outcome); return 0; |