Caveat: I am running linux-2.2.12ow6 which contains many security fixes, yet I believe my comments are still valid. Also I am not a kernel guru. > Basically the problem is that the execve system call > checks that argv is a valid pointer but it doesn't check > that all of the pointers in argv array are valid pointers. The kernel copies each argv[i] into a contiguous chunk of the (soon to be) stack. Thus it must dereference each argv[i]. Check out linux/fs/exec.c line 261 for an almost explicit dereference of argv[i] (memcpy(str,argv+i) except kernel to user space version). This is confirmed by a small test program: #include "nolibc.h" main(int argc, char** argv,char **envp) { int i; char buf[32]; argv[1]=2; i=execve("/bin/sh",argv,envp); /* we should never reach this point, but print out errno in hexadecimal */ i=htonl(i); i=itoh(&i,buf); buf[i]='\n'; write(1,buf,i+1); } This program does not run /bin/sh but istead prints out the message 0000000e representing errno=14, EFAULT. This means the kernel got a segfault while copying the argv[i]'s to the stack, and thus failed the syscall. This program is linked with 'gcc -O -fno-builtin -nostdlib test.c' nolibc.h is ugly but available by request under GPL. It defines ntohl,itoh,write,execve, and _start. Note execve, htonl, itoh, and write are macros. Execve/write are direct system calls. (itoh converts 4 bytes to 8byte hex representation and returns 8, htonl byte swaps so the bytes come out in the right order). > The thing that tipped me off to the problem was that a > program that I exec'd was getting killed with SIGSEGV > in __libc_start_main before my > main function began running. I'm not really sure if this is a widespread problem, but ANYTIME libc gets hosed (malloc(-1) for example) gdb reports the problem occuring in a function called from __libc_start_main and does not ever mention main. I'll study this a wee bit more, since the references I'm using for the startup state don't seem to jive with my experience. (Namely I never see an array of pointers being setup in the docs, and my programs definately do not do so, yet they function and dereference argv as if it were an array of pointers). Another remark: If I misunderstood the bug (like argv[1]=2 obviously is not valid, and is not what you meant) please let me know.
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:07:48 PDT