]> granicus.if.org Git - procps-ng/commitdiff
pgrep: check sanity of SC_ARG_MAX
authorCraig Small <csmall@dropbear.xyz>
Sun, 5 Jan 2020 04:19:41 +0000 (15:19 +1100)
committerCraig Small <csmall@dropbear.xyz>
Sun, 5 Jan 2020 04:19:41 +0000 (15:19 +1100)
A kernel change means we cannot trust what sysconf(SC_ARG_MAX)
returns. We clamp it so its more than 4096 and less than 128*1024
which is what findutils does.

References:
 procps-ng/procps#152
 https://git.savannah.gnu.org/cgit/findutils.git/tree/lib/buildcmd.c#n535
 https://lwn.net/Articles/727862/
 commit bb96fc42956c9ed926a1b958ab715f8b4a663dec

pgrep.c

diff --git a/pgrep.c b/pgrep.c
index e54d36e4f73ddbadc7fd2a1692603b2f2f4bb320..0a2c4cc64998d45a4d99447ac5c0a036e68680db 100644 (file)
--- a/pgrep.c
+++ b/pgrep.c
@@ -477,6 +477,27 @@ static regex_t * do_regcomp (void)
     return preg;
 }
 
+/*
+ * SC_ARG_MAX used to return the maximum size a command line can be
+ * however changes to the kernel mean this can be bigger than we can
+ * alloc. Clamp it to 128kB like xargs and friends do
+ * Should also not be smaller than POSIX_ARG_MAX which is 4096
+ */
+static size_t get_arg_max(void)
+{
+#define MIN_ARG_SIZE 4096u
+#define MAX_ARG_SIZE (128u * 1024u)
+
+    size_t val = sysconf(_SC_ARG_MAX);
+
+    if (val < MIN_ARG_SIZE)
+       val = MIN_ARG_SIZE;
+    if (val > MAX_ARG_SIZE)
+       val = MAX_ARG_SIZE;
+
+    return val;
+}
+
 static struct el * select_procs (int *num)
 {
 #define PIDS_GETINT(e) PIDS_VAL(EU_ ## e, s_int, stack, info)
@@ -494,7 +515,7 @@ static struct el * select_procs (int *num)
     regex_t *preg;
     pid_t myself = getpid();
     struct el *list = NULL;
-    long cmdlen = sysconf(_SC_ARG_MAX) * sizeof(char);
+    long cmdlen = get_arg_max() * sizeof(char);
     char *cmdline = xmalloc(cmdlen);
     char *cmdsearch = xmalloc(cmdlen);
     char *cmdoutput = xmalloc(cmdlen);