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