find(1) uses ARG_MAX to compute the maximum space it can pass to
execve(2).  This doesn't fly if userland and the kernel don't agree, as
noticed by some after the recent ARG_MAX bump.

--8<--
ritchie /usr/src/usr.bin/find$ obj/find /usr/src/ -type f -exec true {} +
find: true: Argument list too long
find: true: Argument list too long
find: true: Argument list too long
^C
-->8--

While having the kernel and userland out of sync is not a good idea,
making find(1) more robust by using sysconf(3) is easy.  This is what
xargs(1) already does.

ok?

PS: a followup diff will take into account the space taken by the
environment


Index: function.c
===================================================================
RCS file: /d/cvs/src/usr.bin/find/function.c,v
retrieving revision 1.47
diff -u -p -p -u -r1.47 function.c
--- function.c  28 Jun 2019 13:35:01 -0000      1.47
+++ function.c  9 Apr 2020 01:36:14 -0000
@@ -538,7 +538,7 @@ run_f_exec(PLAN *plan)
  *
  *     If -exec ... {} +, use only the first array, but make it large
  *     enough to hold 5000 args (cf. src/usr.bin/xargs/xargs.c for a
- *     discussion), and then allocate ARG_MAX - 4K of space for args.
+ *     discussion), and then allocate space for args.
  */
 PLAN *
 c_exec(char *unused, char ***argvp, int isok)
@@ -587,6 +587,7 @@ c_exec(char *unused, char ***argvp, int 
                errx(1, "-ok: terminating \"+\" not permitted.");
 
        if (new->flags & F_PLUSSET) {
+               long arg_max;
                u_int c, bufsize;
 
                cnt = ap - *argvp - 1;                  /* units are words */
@@ -599,6 +600,14 @@ c_exec(char *unused, char ***argvp, int 
                new->ep_narg = 0;
 
                /*
+                * Compute the maximum space we can use for arguments
+                * passed to execve(2).
+                */
+               arg_max = sysconf(_SC_ARG_MAX);
+               if (arg_max == -1)
+                       err(1, "sysconf(_SC_ARG_MAX) failed");
+
+               /*
                 * Count up the space of the user's arguments, and
                 * subtract that from what we allocate.
                 */
@@ -608,8 +617,7 @@ c_exec(char *unused, char ***argvp, int 
                        c += strlen(*argv) + 1;
                        new->e_argv[cnt] = *argv;
                }
-               bufsize = ARG_MAX - 4 * 1024 - c;
-
+               bufsize = arg_max - 4 * 1024 - c;
 
                /*
                 * Allocate, and then initialize current, base, and


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to