Date: Wed, 9 Jan 2002 20:28:52 +0100 From: Marc Olzheim <marcolz@stack.nl>, Serge van den Boom <svdb@stack.nl> To: FreeBSD-gnats-submit@freebsd.org Cc: Marc Olzheim <marcolz@stack.nl>, Serge van den Boom <svdb@stack.nl> Subject: kern/33738: [PATCH] empty argv Message-ID: <20020109202852.A61938@stack.nl>
next in thread | raw e-mail | index | archive | help
>Number: 33738 >Category: kern >Synopsis: argv == NULL is not handled correctly by programs. >Confidential: no >Severity: serious >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jan 09 11:30:01 PST 2002 >Closed-Date: >Last-Modified: >Originator: Marc Olzheim and Serge van den Boom >Release: FreeBSD 4.5-PRERELEASE >Organization: M.C.G.V. Stack >Environment: FreeBSD 2, 3, 4, 5 >Description: FreeBSD's execve(2) does not check wether argv is NULL. This does not seem to pose an immediate threat, but programs like passwd and other setuid programs that use getopt(3) tend to use the example code from the getopt(3) manpage. This code does: argc -= optind; argv += optind; If argc was 0, getopt(3) returns -1 and does not modify optind, which is initialized at 1. Thus argc becomes -1 and argv skips over the NULL pointer into the environment, which is loaded right after the argv strings array in memory. Programs that do not check argc before or after getopt(3) then regard the environment strings as arguments to the program. A good example is ls(1). None of this poses any serious problems, besides from crashing setuid programs, which do not look good in your dmesg, but this could be a problem in programs that handle arguments like ls(1). OpenBSD does not allow empty argv, returning -1 and EFAULT in errno (the man page says it should return EINVAL, but it doesn't). I do not know wether this is a good option for FreeBSD as well, but I don't see any problems with the kernel patch right now. If this patch is not possible for some reason, I think some programs need to be checked for misuse of argv, like ls(1) does. >How-To-Repeat: Attached are noargv.c, which takes a single argument and runs it with argv set to NULL, and 2 patches: one for the kernel and one for getopt(3), which does not do as is should according to the manual. Play around with noargv and see what happens... >Fix: Attached. The getopt patch fixes ls, but not passwd and probably some more programs... Marc --LQksG6bCIzRHxTLp Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="kern_exec.c.patch" --- /usr/src/sys/kern/kern_exec.c.orig Wed Jan 9 19:28:25 2002 +++ /usr/src/sys/kern/kern_exec.c Wed Jan 9 19:30:33 2002 @@ -582,7 +582,8 @@ imgp->argc++; } while ((argp = (caddr_t) (intptr_t) fuword(argv++))); } - } + } else + return(EFAULT); imgp->endargs = imgp->stringp; --LQksG6bCIzRHxTLp Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="getopt.c.patch" --- /usr/src/lib/libc/stdlib/getopt.c Wed Jan 9 16:26:37 2002 +++ /usr/src/lib/libc/stdlib/getopt.c Wed Jan 9 16:51:27 2002 @@ -66,6 +66,15 @@ static char *place = EMSG; /* option letter processing */ char *oli; /* option letter list index */ + if (!nargc) + { + optind = 0; + if (optreset) + optreset = 0; + + return (-1); + } + if (optreset || !*place) { /* update scanning pointer */ optreset = 0; if (optind >= nargc || *(place = nargv[optind]) != '-') { --LQksG6bCIzRHxTLp-- >Release-Note: >Audit-Trail: >Unformatted: --LQksG6bCIzRHxTLp Content-Type: text/plain; charset=us-ascii Content-Disposition: inline To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020109202852.A61938>