Skip site navigation (1)Skip section navigation (2)
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>