Bugtraq mailing list archives

Re: execve bug linux-2.2.12


From: timof () URANOS QUANTUM PHYSIK UNI-POTSDAM DE (Timo Felbinger)
Date: Wed, 20 Oct 1999 18:21:44 +0200


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.Felbinger () quantum physik uni-potsdam de>
Quantum Physics Group    <http://www.quantum.physik.uni-potsdam.de/TF>
Institut fuer Physik
Universitaet Potsdam, Germany



Current thread: