kern/58803: kern.argmax isn't changeable even at boot [PATCH]
Per Hedeland
per at hedeland.org
Sun Nov 23 12:40:19 PST 2003
The following reply was made to PR kern/58803; it has been noted by GNATS.
From: Per Hedeland <per at hedeland.org>
To: bde at zeta.org.au, freebsd-gnats-submit at freebsd.org
Cc:
Subject: Re: kern/58803: kern.argmax isn't changeable even at boot [PATCH]
Date: Sun, 23 Nov 2003 21:32:33 +0100 (CET)
Bruce Evans <bde at zeta.org.au> wrote:
>
>On Sun, 2 Nov 2003, Per Hedeland wrote:
>
>> Bruce Evans <bde at zeta.org.au> wrote:
>
>> > ...
>> >Traditionally hardwired constants cannot usefully be replaced by
>> >tunables without removing the hardwired constants. Otherwise all the
>> >users of the hardwired constants get wrong values if the tunables are
>> >actually used.
>>
>> Yes, though from a pragmatic point of view I would still think that as
>> long as this doesn't cause malfunction, it would be preferable to
>> breaking existing code that would still function with a constant but
>> incorrect definition.
>> ...
>> So, would the patch be acceptable if it also
>>
>> a) Fixed the usage of ARG_MAX in the source tree
>> b) Made the constant definition be equal to _POSIX_ARG_MAX
>> c) Prevented setting the tunable lower than _POSIX_ARG_MAX
>>
>> ? Removing the definition altogether would of course be just as simple
>> as b),
>
>That would be enough for me, except don't do (b) (leave ARG_MAX with its
>current value which is larger than _POSIX_ARG_MAX until most or all ports
>are fixed). Fixing all ports is too much to expect from anyone.
OK, I finally got around to looking at this again - an "interesting"
exercise... An updated patch is enclosed.
>Many things in the tree already use only sysconf(_SC_ARG_MAX). The
>most interesting exceptions are glob(3) (libc/gen/glob.c) and sh(1).
>glob() just uses ARG_MAX, and sh(1) doesn't use any of glob(), ARG_MAX
>or sysconf().
The glob(3) usage seems quite broken to me - it uses ARG_MAX as the
default limit on the *number* of matches when GLOB_LIMIT is set, which
is hardly meaningful. Apparently this behaviour was introduced in an
attempt make glob(3) more compatible with the NetBSD/OpenBSD
implementations, but the result is something that isn't compatible with
either the previous FreeBSD implementation or the others (which use
ARG_MAX to limit the *total size* of the matches).
Fixing that is beyond the scope for this patch I think - but since the
usage is totally unrelated to the value returned by sysconf(), I saw no
reason to put in a call to that, but simply fall back to _POSIX_ARG_MAX
if ARG_MAX isn't #defined. I applied similar reasoning to
libc/{alpha,i386}/gen/makecontext.c.
>> I just feel that it would cause unnecessary breakage. And, what
>> about NCARGS?
>
>NCARGS should have gone away when ARG_MAX became standard, so it should
>be easier to remove now. NCARGS is used mainly in tcsh. tcsh has ifdefs
>to use sysconf() if neither NCARGS nor ARG_MAX exists, but they are poorly
>implemented and just define NCARGS in terms of sysconf() so all the
>references to NCARGS in tcsh become slow.
Fixed that, and rshd/rexecd used NCARGS too. The remaining "unprotected"
usage of NCARGS/ARG_MAX was in libc/posix1e/mac.c, where it was used to
size an unused array... (already fixed in CVS).
--Per Hedeland
per at hedeland.org
=================================================================
--- /usr/src/sys/alpha/osf1/osf1_sysvec.c.ORIG Sun Sep 1 23:41:22 2002
+++ /usr/src/sys/alpha/osf1/osf1_sysvec.c Thu Oct 30 01:25:25 2003
@@ -121,7 +121,7 @@
sz = *(imgp->proc->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
- roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+ roundup((argmax - imgp->stringspace), sizeof(char *));
destp -= imgp->stringspace;
--- /usr/src/sys/ia64/ia32/ia32_sysvec.c.ORIG Sun Sep 1 23:41:23 2002
+++ /usr/src/sys/ia64/ia32/ia32_sysvec.c Thu Oct 30 01:25:25 2003
@@ -146,7 +146,7 @@
arginfo = (struct ia32_ps_strings *)IA32_PS_STRINGS;
szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
- roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+ roundup((argmax - imgp->stringspace), sizeof(char *));
/*
* install sigcode
@@ -194,7 +194,7 @@
/*
* Copy out strings - arguments and environment.
*/
- copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+ copyout(stringp, destp, argmax - imgp->stringspace);
/*
* Fill in "ps_strings" struct for ps, w, etc.
--- /usr/src/sys/kern/kern_exec.c.ORIG Thu Dec 19 10:40:10 2002
+++ /usr/src/sys/kern/kern_exec.c Thu Oct 30 01:27:26 2003
@@ -235,7 +235,7 @@
* Allocate temporary demand zeroed space for argument and
* environment strings
*/
- imgp->stringbase = (char *)kmem_alloc_wait(exec_map, ARG_MAX +
+ imgp->stringbase = (char *)kmem_alloc_wait(exec_map, argmax +
PAGE_SIZE);
if (imgp->stringbase == NULL) {
error = ENOMEM;
@@ -243,8 +243,8 @@
goto exec_fail;
}
imgp->stringp = imgp->stringbase;
- imgp->stringspace = ARG_MAX;
- imgp->image_header = imgp->stringbase + ARG_MAX;
+ imgp->stringspace = argmax;
+ imgp->image_header = imgp->stringbase + argmax;
/*
* Translate the file name. namei() returns a vnode pointer
@@ -260,7 +260,7 @@
error = namei(ndp);
if (error) {
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
- ARG_MAX + PAGE_SIZE);
+ argmax + PAGE_SIZE);
goto exec_fail;
}
@@ -633,7 +633,7 @@
if (imgp->stringbase != NULL)
kmem_free_wakeup(exec_map, (vm_offset_t)imgp->stringbase,
- ARG_MAX + PAGE_SIZE);
+ argmax + PAGE_SIZE);
if (imgp->object)
vm_object_deallocate(imgp->object);
@@ -987,7 +987,7 @@
if (p->p_sysent->sv_szsigcode != NULL)
szsigcode = *(p->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
- roundup((ARG_MAX - imgp->stringspace), sizeof(char *));
+ roundup((argmax - imgp->stringspace), sizeof(char *));
/*
* install sigcode
@@ -1035,7 +1035,7 @@
/*
* Copy out strings - arguments and environment.
*/
- copyout(stringp, destp, ARG_MAX - imgp->stringspace);
+ copyout(stringp, destp, argmax - imgp->stringspace);
/*
* Fill in "ps_strings" struct for ps, w, etc.
--- /usr/src/sys/kern/kern_mib.c.ORIG Fri Nov 8 00:57:17 2002
+++ /usr/src/sys/kern/kern_mib.c Thu Oct 30 01:27:27 2003
@@ -111,7 +111,7 @@
&maxusers, 0, "Hint for kernel tuning");
SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD,
- 0, ARG_MAX, "Maximum bytes of argument to execve(2)");
+ &argmax, 0, "Maximum bytes of argument to execve(2)");
SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD,
0, _POSIX_VERSION, "Version of POSIX attempting to comply to");
--- /usr/src/sys/kern/subr_param.c.ORIG Fri Aug 30 06:04:35 2002
+++ /usr/src/sys/kern/subr_param.c Sun Nov 23 19:42:30 2003
@@ -62,6 +62,12 @@
#ifndef MAXFILES
#define MAXFILES (maxproc * 2)
#endif
+#ifndef ARG_MAX
+#define ARG_MAX 65536
+#endif
+#ifndef _POSIX_ARG_MAX
+#define _POSIX_ARG_MAX 4096
+#endif
int hz;
int tick;
@@ -75,6 +81,7 @@
int nswbuf;
int maxswzone; /* max swmeta KVA storage */
int maxbcache; /* max buffer cache KVA storage */
+int argmax; /* max bytes of argument to exec */
u_quad_t maxtsiz; /* max text size */
u_quad_t dfldsiz; /* initial data size limit */
u_quad_t maxdsiz; /* max data size */
@@ -166,4 +173,9 @@
ncallout = 16 + maxproc + maxfiles;
TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
+
+ argmax = ARG_MAX;
+ TUNABLE_INT_FETCH("kern.argmax", &argmax);
+ if (argmax < _POSIX_ARG_MAX)
+ argmax = _POSIX_ARG_MAX;
}
--- /usr/src/sys/sys/proc.h.ORIG Tue Dec 10 03:33:45 2002
+++ /usr/src/sys/sys/proc.h Thu Oct 30 01:27:29 2003
@@ -827,6 +827,7 @@
extern int hogticks; /* Limit on kernel cpu hogs. */
extern int nprocs, maxproc; /* Current and max number of procs. */
extern int maxprocperuid; /* Max procs per uid. */
+extern int argmax; /* Max bytes of argument to exec. */
extern u_long ps_arg_cache_limit;
extern int ps_argsopen;
extern int ps_showallprocs;
--- /usr/src/sys/vm/vm_init.c.ORIG Fri Nov 8 00:57:17 2002
+++ /usr/src/sys/vm/vm_init.c Thu Oct 30 01:25:25 2003
@@ -193,7 +193,7 @@
(nswbuf*MAXPHYS) + pager_map_size);
pager_map->system_map = 1;
exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
- (16*(ARG_MAX+(PAGE_SIZE*3))));
+ (16*(argmax+(PAGE_SIZE*3))));
/*
* XXX: Mbuf system machine-specific initializations should
--- /usr/src/contrib/tcsh/ed.chared.c.ORIG Wed Jul 24 18:22:56 2002
+++ /usr/src/contrib/tcsh/ed.chared.c Sun Nov 23 14:31:58 2003
@@ -514,7 +514,7 @@
}
if (*p == '$') {
if (*++p != '-') {
- *num = NCARGS; /* Handle $ */
+ *num = ArgMax; /* Handle $ */
return(--p);
}
sign = -1; /* Handle $- */
@@ -562,13 +562,13 @@
break;
case '*':
- bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, NCARGS);
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 1, ArgMax);
break;
default:
if (been_once) { /* unknown argument */
/* assume it's a modifier, e.g. !foo:h, and get whole cmd */
- bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, ArgMax);
q -= 2;
break;
}
@@ -661,7 +661,7 @@
}
else if (q[1] == '*') {
++q;
- to = NCARGS;
+ to = ArgMax;
}
else {
to = from;
@@ -671,7 +671,7 @@
bend = expand_lex(buf, INBUFSIZE, &h->Hlex, from, to);
}
else { /* get whole cmd */
- bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, NCARGS);
+ bend = expand_lex(buf, INBUFSIZE, &h->Hlex, 0, ArgMax);
}
break;
}
@@ -2255,7 +2255,7 @@
hp = hp->Hnext;
if (hp == NULL) /* "can't happen" */
return(CC_ERROR);
- cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, ArgMax);
*cp = '\0';
bp = hbuf;
hp = hp->Hnext;
@@ -2277,7 +2277,7 @@
word = 0;
if (hp == NULL)
return(CC_ERROR);
- cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, NCARGS);
+ cp = expand_lex(hbuf, INBUFSIZE, &hp->Hlex, 0, ArgMax);
*cp = '\0';
bp = hbuf;
hp = hp->Hnext;
--- /usr/src/contrib/tcsh/sh.h.ORIG Wed Jul 24 18:23:01 2002
+++ /usr/src/contrib/tcsh/sh.h Sun Nov 23 15:03:33 2003
@@ -650,6 +650,7 @@
*/
EXTERN Char *doldol; /* Character pid for $$ */
EXTERN int backpid; /* pid of the last background job */
+EXTERN int ArgMax; /* Max bytes for an exec function */
/*
* Ideally these should be uid_t, gid_t, pid_t. I cannot do that right now
--- /usr/src/contrib/tcsh/tc.func.c.ORIG Wed Jul 24 18:23:04 2002
+++ /usr/src/contrib/tcsh/tc.func.c Sun Nov 23 15:33:34 2003
@@ -134,7 +134,7 @@
if (sp == (sp0 = sp0->prev))
return (buf); /* nada */
- for (i = 0; i < NCARGS; i++) {
+ for (i = 0; i < ArgMax; i++) {
if ((i >= from) && (i <= to)) { /* if in range */
for (s = sp->word; *s && d < e; s++) {
/*
@@ -174,7 +174,7 @@
{
Char *cp;
- cp = expand_lex(buf, bufsiz, sp0, 0, NCARGS);
+ cp = expand_lex(buf, bufsiz, sp0, 0, ArgMax);
*cp = '\0';
return (buf);
}
--- /usr/src/contrib/tcsh/tc.os.c.ORIG Wed Jul 24 18:23:04 2002
+++ /usr/src/contrib/tcsh/tc.os.c Sun Nov 23 15:05:10 2003
@@ -979,6 +979,24 @@
*/
syscall(151, getpid(), getpid());
#endif /* _SX */
+
+#ifndef NCARGS
+# ifdef _SC_ARG_MAX
+# define NCARGS sysconf(_SC_ARG_MAX)
+# else /* !_SC_ARG_MAX */
+# ifdef ARG_MAX
+# define NCARGS ARG_MAX
+# else /* !ARG_MAX */
+# ifdef _MINIX
+# define NCARGS 80
+# else /* !_MINIX */
+# define NCARGS 1024
+# endif /* _MINIX */
+# endif /* ARG_MAX */
+# endif /* _SC_ARG_MAX */
+#endif /* NCARGS */
+ ArgMax = NCARGS;
+
}
#ifdef strerror
--- /usr/src/contrib/tcsh/tc.os.h.ORIG Wed Jul 24 18:23:04 2002
+++ /usr/src/contrib/tcsh/tc.os.h Sun Nov 23 15:03:49 2003
@@ -105,22 +105,6 @@
# endif /* POSIX */
#endif /* OREO */
-#ifndef NCARGS
-# ifdef _SC_ARG_MAX
-# define NCARGS sysconf(_SC_ARG_MAX)
-# else /* !_SC_ARG_MAX */
-# ifdef ARG_MAX
-# define NCARGS ARG_MAX
-# else /* !ARG_MAX */
-# ifdef _MINIX
-# define NCARGS 80
-# else /* !_MINIX */
-# define NCARGS 1024
-# endif /* _MINIX */
-# endif /* ARG_MAX */
-# endif /* _SC_ARG_MAX */
-#endif /* NCARGS */
-
#ifdef convex
# include <sys/dmon.h>
#endif /* convex */
--- /usr/src/lib/libc/alpha/gen/makecontext.c.ORIG Sat Nov 16 07:39:10 2002
+++ /usr/src/lib/libc/alpha/gen/makecontext.c Sun Nov 23 21:25:31 2003
@@ -30,11 +30,19 @@
#include <sys/param.h>
#include <sys/signal.h>
+#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#include <ucontext.h>
#include <unistd.h>
+/*
+ * The usage of ARG_MAX (or NCARGS) as limit on argc seems arbitrary at best
+ * - thus there is little point in finding the actual value via sysconf(3).
+ */
+#ifndef ARG_MAX
+#define ARG_MAX _POSIX_ARG_MAX
+#endif
/* Prototypes */
extern void _ctx_start(int argc, ...);
@@ -83,7 +91,7 @@
ucp->uc_mcontext.mc_format = 0;
}
/* XXX - Do we want to sanity check argc? */
- else if ((argc < 0) || (argc > NCARGS)) {
+ else if ((argc < 0) || (argc > ARG_MAX)) {
ucp->uc_mcontext.mc_format = 0;
}
/*
--- /usr/src/lib/libc/gen/glob.c.ORIG Wed Jul 17 06:58:09 2002
+++ /usr/src/lib/libc/gen/glob.c Sun Nov 23 21:14:43 2003
@@ -68,6 +68,7 @@
#include <sys/param.h>
#include <sys/stat.h>
+#include <limits.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
@@ -77,6 +78,15 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
+/*
+ * The usage of ARG_MAX as default limit on the *number* of matches seems
+ * arbitrary at best - it should rather limit their total size. Given this,
+ * there is little point in finding the actual value via sysconf(3).
+ */
+#ifndef ARG_MAX
+#define ARG_MAX _POSIX_ARG_MAX
+#endif
#include "collate.h"
--- /usr/src/lib/libc/i386/gen/makecontext.c.ORIG Mon Sep 16 21:24:31 2002
+++ /usr/src/lib/libc/i386/gen/makecontext.c Sun Nov 23 21:25:41 2003
@@ -31,11 +31,20 @@
#include <sys/signal.h>
#include <sys/ucontext.h>
+#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
+/*
+ * The usage of ARG_MAX (or NCARGS) as limit on argc seems arbitrary at best
+ * - thus there is little point in finding the actual value via sysconf(3).
+ */
+#ifndef ARG_MAX
+#define ARG_MAX _POSIX_ARG_MAX
+#endif
+
/* Prototypes */
extern void _ctx_start(ucontext_t *, int argc, ...);
@@ -83,7 +92,7 @@
ucp->uc_mcontext.mc_len = 0;
}
/* XXX - Do we want to sanity check argc? */
- else if ((argc < 0) || (argc > NCARGS)) {
+ else if ((argc < 0) || (argc > ARG_MAX)) {
ucp->uc_mcontext.mc_len = 0;
}
/* Make sure the context is valid. */
--- /usr/src/lib/libc/posix1e/mac.c.ORIG Tue Nov 5 02:42:35 2002
+++ /usr/src/lib/libc/posix1e/mac.c Sun Nov 23 15:16:18 2003
@@ -97,7 +97,6 @@
return (0);
while (fgets(line, LINE_MAX, file)) {
- char *argv[ARG_MAX];
char *arg, *parse, *statement, *policyname, *modulename;
int argc;
--- /usr/src/libexec/rexecd/rexecd.c.ORIG Fri May 3 15:12:06 2002
+++ /usr/src/libexec/rexecd/rexecd.c Sun Nov 23 14:24:24 2003
@@ -129,7 +129,8 @@
static void
doit(struct sockaddr *fromp)
{
- char cmdbuf[NCARGS+1], *cp;
+ char *cmdbuf, *cp;
+ int argmax;
const char *namep;
char user[16], pass[16];
struct passwd *pwd;
@@ -178,9 +179,14 @@
if (connect(sd, fromp, fromp->sa_len) < 0)
exit(1);
}
+ if ((argmax = sysconf(_SC_ARG_MAX)) == -1 ||
+ (cmdbuf = malloc(argmax + 1)) == NULL) {
+ error("%s.", strerror(errno));
+ exit(1);
+ }
getstr(user, sizeof(user), "username");
getstr(pass, sizeof(pass), "password");
- getstr(cmdbuf, sizeof(cmdbuf), "command");
+ getstr(cmdbuf, argmax + 1, "command");
(void) alarm(0);
if ((pwd = getpwnam(user)) == NULL || (pwd->pw_uid = 0 && no_uid_0) ||
@@ -207,6 +213,7 @@
}
if (pid) {
/* parent */
+ free(cmdbuf);
(void) pam_end(pamh, pam_err);
(void) close(STDIN_FILENO);
(void) close(STDOUT_FILENO);
--- /usr/src/libexec/rshd/rshd.c.ORIG Wed Jun 26 19:09:08 2002
+++ /usr/src/libexec/rshd/rshd.c Sun Nov 23 14:26:34 2003
@@ -194,7 +194,9 @@
int one = 1;
const char *cp, *errorstr;
char sig, buf[BUFSIZ];
- char cmdbuf[NCARGS+1], luser[16], ruser[16];
+ char *cmdbuf;
+ int argmax;
+ char luser[16], ruser[16];
char rhost[2 * MAXHOSTNAMELEN + 1];
char numericname[INET6_ADDRSTRLEN];
int af, srcport;
@@ -297,10 +299,14 @@
rhost[sizeof(rhost) - 1] = '\0';
/* XXX truncation! */
+ if ((argmax = sysconf(_SC_ARG_MAX)) == -1 ||
+ (cmdbuf = malloc(argmax + 1)) == NULL) {
+ rshd_errx(1, "%s.", strerror(errno));
+ }
(void) alarm(60);
getstr(ruser, sizeof(ruser), "ruser");
getstr(luser, sizeof(luser), "luser");
- getstr(cmdbuf, sizeof(cmdbuf), "command");
+ getstr(cmdbuf, argmax + 1, "command");
(void) alarm(0);
pam_err = pam_start("rsh", luser, &pamc, &pamh);
@@ -403,6 +409,7 @@
if (pid == -1)
rshd_errx(1, "Can't fork; try again.");
if (pid) {
+ free(cmdbuf);
(void) close(0);
(void) close(1);
(void) close(2);
@@ -459,6 +466,7 @@
rshd_errx(1, "Can't fork; try again.");
if (pid) {
/* Parent. */
+ free(cmdbuf);
while (wait(NULL) > 0 || errno == EINTR)
/* nothing */ ;
PAM_END;
More information about the freebsd-bugs
mailing list