ff6046
From 6298317e2d0dffb1ff4ecebedb8709645de36b6a Mon Sep 17 00:00:00 2001
ff6046
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
ff6046
Date: Wed, 5 Dec 2018 18:48:23 +0100
ff6046
Subject: [PATCH] basic/process-util: limit command line lengths to _SC_ARG_MAX
ff6046
ff6046
This affects systemd-journald and systemd-coredump.
ff6046
ff6046
Example entry:
ff6046
$ journalctl -o export -n1 'MESSAGE=Something logged'
ff6046
__CURSOR=s=976542d120c649f494471be317829ef9;i=34e;b=4871e4c474574ce4a462dfe3f1c37f06;m=c7d0c37dd2;t=57c4ac58f3b98;x=67598e942bd23dc0
ff6046
__REALTIME_TIMESTAMP=1544035467475864
ff6046
__MONOTONIC_TIMESTAMP=858200964562
ff6046
_BOOT_ID=4871e4c474574ce4a462dfe3f1c37f06
ff6046
PRIORITY=6
ff6046
_UID=1000
ff6046
_GID=1000
ff6046
_CAP_EFFECTIVE=0
ff6046
_SELINUX_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
ff6046
_AUDIT_SESSION=1
ff6046
_AUDIT_LOGINUID=1000
ff6046
_SYSTEMD_OWNER_UID=1000
ff6046
_SYSTEMD_UNIT=user@1000.service
ff6046
_SYSTEMD_SLICE=user-1000.slice
ff6046
_SYSTEMD_USER_SLICE=-.slice
ff6046
_SYSTEMD_INVOCATION_ID=1c4a469986d448719cb0f9141a10810e
ff6046
_MACHINE_ID=08a5690a2eed47cf92ac0a5d2e3cf6b0
ff6046
_HOSTNAME=krowka
ff6046
_TRANSPORT=syslog
ff6046
SYSLOG_FACILITY=17
ff6046
SYSLOG_IDENTIFIER=syslog-caller
ff6046
MESSAGE=Something logged
ff6046
_COMM=poc
ff6046
_EXE=/home/zbyszek/src/systemd-work3/poc
ff6046
_SYSTEMD_CGROUP=/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service
ff6046
_SYSTEMD_USER_UNIT=gnome-terminal-server.service
ff6046
SYSLOG_PID=4108
ff6046
SYSLOG_TIMESTAMP=Dec  5 19:44:27
ff6046
_PID=4108
ff6046
_CMDLINE=./poc AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>
ff6046
_SOURCE_REALTIME_TIMESTAMP=1544035467475848
ff6046
ff6046
$ journalctl -o export -n1 'MESSAGE=Something logged' --output-fields=_CMDLINE|wc
ff6046
      6    2053 2097410
ff6046
ff6046
2MB might be hard for some clients to use meaningfully, but OTOH, it is
ff6046
important to log the full commandline sometimes. For example, when the program
ff6046
is crashing, the exact argument list is useful.
ff6046
ff6046
(cherry-picked from commit 2d5d2e0cc5171c6795d2a485841474345d9e30ab)
ff6046
ff6046
Related: #1664976
ff6046
---
ff6046
 src/basic/process-util.c | 73 ++++++++++++++--------------------------
ff6046
 1 file changed, 25 insertions(+), 48 deletions(-)
ff6046
ff6046
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
ff6046
index 0a4f917cbd..a20f1e3ccf 100644
ff6046
--- a/src/basic/process-util.c
ff6046
+++ b/src/basic/process-util.c
ff6046
@@ -128,6 +128,13 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
ff6046
 
ff6046
         (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
ff6046
 
ff6046
+        if (max_length == 0) {
ff6046
+                /* This is supposed to be a safety guard against runaway command lines. */
ff6046
+                long l = sysconf(_SC_ARG_MAX);
ff6046
+                assert(l > 0);
ff6046
+                max_length = l;
ff6046
+        }
ff6046
+
ff6046
         if (max_length == 1) {
ff6046
 
ff6046
                 /* If there's only room for one byte, return the empty string */
ff6046
@@ -138,32 +145,6 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
ff6046
                 *line = ans;
ff6046
                 return 0;
ff6046
 
ff6046
-        } else if (max_length == 0) {
ff6046
-                size_t len = 0, allocated = 0;
ff6046
-
ff6046
-                while ((c = getc(f)) != EOF) {
ff6046
-
ff6046
-                        if (!GREEDY_REALLOC(ans, allocated, len+3)) {
ff6046
-                                free(ans);
ff6046
-                                return -ENOMEM;
ff6046
-                        }
ff6046
-
ff6046
-                        if (isprint(c)) {
ff6046
-                                if (space) {
ff6046
-                                        ans[len++] = ' ';
ff6046
-                                        space = false;
ff6046
-                                }
ff6046
-
ff6046
-                                ans[len++] = c;
ff6046
-                        } else if (len > 0)
ff6046
-                                space = true;
ff6046
-               }
ff6046
-
ff6046
-                if (len > 0)
ff6046
-                        ans[len] = '\0';
ff6046
-                else
ff6046
-                        ans = mfree(ans);
ff6046
-
ff6046
         } else {
ff6046
                 bool dotdotdot = false;
ff6046
                 size_t left;
ff6046
@@ -235,34 +216,30 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
ff6046
                 if (h < 0)
ff6046
                         return h;
ff6046
 
ff6046
-                if (max_length == 0)
ff6046
-                        ans = strjoin("[", t, "]");
ff6046
-                else {
ff6046
-                        size_t l;
ff6046
-
ff6046
-                        l = strlen(t);
ff6046
+                size_t l = strlen(t);
ff6046
 
ff6046
-                        if (l + 3 <= max_length)
ff6046
-                                ans = strjoin("[", t, "]");
ff6046
-                        else if (max_length <= 6) {
ff6046
+                if (l + 3 <= max_length) {
ff6046
+                        ans = strjoin("[", t, "]");
ff6046
+                        if (!ans)
ff6046
+                                return -ENOMEM;
ff6046
 
ff6046
-                                ans = new(char, max_length);
ff6046
-                                if (!ans)
ff6046
-                                        return -ENOMEM;
ff6046
+                } else if (max_length <= 6) {
ff6046
+                        ans = new(char, max_length);
ff6046
+                        if (!ans)
ff6046
+                                return -ENOMEM;
ff6046
 
ff6046
-                                memcpy(ans, "[...]", max_length-1);
ff6046
-                                ans[max_length-1] = 0;
ff6046
-                        } else {
ff6046
-                                t[max_length - 6] = 0;
ff6046
+                        memcpy(ans, "[...]", max_length-1);
ff6046
+                        ans[max_length-1] = 0;
ff6046
+                } else {
ff6046
+                        t[max_length - 6] = 0;
ff6046
 
ff6046
-                                /* Chop off final spaces */
ff6046
-                                delete_trailing_chars(t, WHITESPACE);
ff6046
+                        /* Chop off final spaces */
ff6046
+                        delete_trailing_chars(t, WHITESPACE);
ff6046
 
ff6046
-                                ans = strjoin("[", t, "...]");
ff6046
-                        }
ff6046
+                        ans = strjoin("[", t, "...]");
ff6046
+                        if (!ans)
ff6046
+                                return -ENOMEM;
ff6046
                 }
ff6046
-                if (!ans)
ff6046
-                        return -ENOMEM;
ff6046
         }
ff6046
 
ff6046
         *line = ans;