Re: execve bug linux-2.2.12

From: securityat_private
Date: Sat Oct 16 1999 - 15:13:19 PDT

  • Next message: Nick_: "Re: Multiple vulnerabilities in CDE"

    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