Subject: kern/18334: argc = 0 causes rtld null pointer deref
To: None <>
From: None <>
List: netbsd-bugs
Date: 09/19/2002 10:58:14
>Number:         18334
>Category:       kern
>Synopsis:       argc = 0 causes rtld null pointer deref
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Sep 19 03:01:00 PDT 2002
>Release:        NetBSD 1.6F
System: NetBSD stasis 1.6F NetBSD 1.6F (STASIS) #6: Fri Sep 13 17:07:18 BST 2002 xs@stasis:/usr/src/sys/arch/i386/compile/STASIS i386
Architecture: i386
Machine: i386

     $NetBSD: rtld.c,v 1.52 2002/08/09 10:03:08 soren Exp $

     $NetBSD: kern_exec.c,v 1.152 2002/04/23 15:11:25 christos Exp $

The kernel does not enforce the following part of the execve(2) man page: 

     The argument argv is a pointer to a null-terminated array of character
     pointers to null-terminated character strings.  These strings construct
     the argument list to be made available to the new process.	 At least one
     argument must be present in the array; by custom, the first element
     should be the name of the executed program (for example, the last compo-
     nent of path).

hence any dynamically linked program can be segfaulted because the rtld
assumes argv[0] is a valid address in rtld() where it invokes strrchr
on argv[0] to determine a value for __progname. Other code in rtld()
explicitly permits a NULL argv[0] though..

$ cat rtld-core.c
#include <unistd.h>

main(int argc, char *argv[])
	char *args[] = { NULL };

	execv(argv[1], args);
	return 1;

$ make rtld-core
$ export LD_DEBUG=1; ./rtld-core ./rtld-core
relocating objects
doing copy relocations
Segmentation fault (core dumped)

Force argc to be at least 1 in sys_execve() and/or make rtld() deal
with argc == 0 correctly.

Index: kern_exec.c
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.152
diff -u -r1.152 kern_exec.c
--- kern_exec.c	2002/04/23 15:11:25	1.152
+++ kern_exec.c	2002/09/13 16:18:23
@@ -434,6 +434,10 @@
+	if (argc < 1) {
+		error = EINVAL;
+		goto bad;
+	}
 	envc = 0;
 	/* environment need not be there */