Re: execve bug linux-2.2.12

From: Timo Felbinger (timofat_private-POTSDAM.DE)
Date: Wed Oct 20 1999 - 09:21:44 PDT

  • Next message: Taneli Huuskonen: "Re: execve bug linux-2.2.12"

    On Tue, 19 Oct 1999, Matt Chapman wrote:
    
    > On Sat, Oct 16, 1999 at 02:22:02PM +0100, Alan Cox wrote:
    > >
    > > I would certainly be interested in an example that caused this.
    >
    > #include <unistd.h>
    > #include <errno.h>
    >
    > #define BADPTR (char *)0x10   /* for example */
    >
    > int main(int argc, char **argv, char **envp)
    > {
    >         char *args[7];
    >         int i;
    >
    >         args[0] = "su";
    >         for (i = 1; i < 6; i++) {
    >                 args[i] = BADPTR;
    >         }
    >         args[6] = NULL;
    >
    >         execve("/bin/su", args, envp);
    >
    >         printf("%s\n", strerror(errno));
    > 	return 1;
    > }
    
    If you do not attempt to call su but instead another test program which
    just prints all its args and environment, it becomes pretty clear what
    is going on:
    
    % cat test.c
    
    #include <unistd.h>
    #include <errno.h>
    
    #define BADPTR (char *)0x01   /* for example */
    
    int main(int argc, char **argv, char **envp)
    {
            char *args[7];
            int i;
    
            for( i = 0; i < 6; ++i )
              printf( "test: envp[%d]: >>>%s<<<\n", i, envp[i] );
            args[0] = "t2";
            for (i = 1; i < 6; i++)
              args[i] = BADPTR;
            args[3] = "smurf";
            args[6] = NULL;
            execve("./t2", args, envp);
            return 1;
    }
    
    % cat t2.c
    
    #include <unistd.h>
    #include <errno.h>
    #include <stdio.h>
    
    int main(int argc, char **argv, char **envp)
    {
      int i;
    
      printf( "argc = %d\n", argc );
      fflush( stdout );
      for( i = 0; argv[i]; ++i ) {
        printf( "t2: argv[%d]: >>>%s<<<\n", i, argv[i] );
        fflush( stdout );  /* flush it, in case we segfault... */
      }
      for( i = 0; envp[i]; ++i ) {
        printf( "t2: envp[%d]: >>>%s<<<\n", i, envp[i] );
        fflush( stdout );
      }
    }
    
    % ./test
    
    test: envp[0]: >>>PWD=/Users/timof/c/test<<<
    test: envp[1]: >>>TMPDIR=/tmp/110<<<
    test: envp[2]: >>>XAUTHORITY=/usr/X11/lib/cookies/0000006E/cookies.be554794d91a8049<<<
    test: envp[3]: >>>WINDOWID=171966478<<<
    test: envp[4]: >>>PAGER=/usr/bin/less<<<
    test: envp[5]: >>>HZ=100<<<
    argc = 6
    t2: argv[0]: >>>t2<<<
    t2: argv[1]: >>>smurf<<<
    t2: argv[2]: >>>PWD=/Users/timof/c/test<<<
    t2: argv[3]: >>>TMPDIR=/tmp/110<<<
    t2: argv[4]: >>>XAUTHORITY=/usr/X11/lib/cookies/0000006E/cookies.be554794d91a8049<<<
    t2: argv[5]: >>>WINDOWID=171966478<<<
    t2: envp[0]: >>>PAGER=/usr/bin/less<<<
    t2: envp[1]: >>>HZ=100<<<
    
    [snip]
    
    t2: envp[36]: >>>_=./test<<<
    t2: envp[37]: >>>OLDPWD=/Users/timof/tmp<<<
    t2: envp[38]: >>>./t2<<<
    t2: envp[39]: >>><<<
    t2: envp[40]: >>><<<
    t2: envp[41]: >>><<<
    
    It seems that the argc of the new process is based on the number
    of non-NULL entries in the argv passed to the execve call, but the
    loop in the kernel copying the strings to the stack skips over
    invalid pointers in argv without reliably indicating an error, and
    without putting anything (not even a NUL) on the stack,
    
    The ELF loader then interprets the first environment strings as args
    and creates a few invalid entries near the end of envp. Maybe these can
    cause a SIGSEGV (which I could not reproduce).
    
    Timo Felbinger
    
    --
    Timo Felbinger           <Timo.Felbingerat_private-potsdam.de>
    Quantum Physics Group    <http://www.quantum.physik.uni-potsdam.de/TF>
    Institut fuer Physik
    Universitaet Potsdam, Germany
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:08:08 PDT