summaryrefslogtreecommitdiff
path: root/src/basic
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-12-17 11:23:15 +0100
committerLennart Poettering <lennart@poettering.net>2018-12-18 15:03:05 +0100
commit2a7797e964e5b6a0f305b00073e2b06a195d0b15 (patch)
treecde681201fc40f1824dea692d8feced13343a83a /src/basic
parent03a7dbeae051a5b655eb956f335024bfba8599d1 (diff)
downloadsystemd-2a7797e964e5b6a0f305b00073e2b06a195d0b15.tar.gz
process-util: make get_process_environ() safer
Let's add a size limit, and let's use safe_fgetc().
Diffstat (limited to 'src/basic')
-rw-r--r--src/basic/process-util.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 5b700df33a..ebf613b9db 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;