The second argument to execve
is defined as being a NULL-terminated list of strings, so you can't simply pass the address of path
. It expects an array like this, with the final entry being NULL:
arg[0] = "/bin/ls"
arg[1] = "-l"
arg[2] = "/usr/include/std*"
arg[3] = NULL
The reason it was failing with a bad pointer is that execve
would have been looking at each word following path
to find the arguments, and treating each word as a pointer until it got to the first 0 word. Since path
was alone on the stack, it would have been trying to interpret whatever garbage happened to be in memory after the stack beyond path
as a string pointer.
The solution is simple: you need to construct an array of parameters and add a NULL terminator (since it is of variable length). The fixed example is below (with a few warnings taken care of):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
int main()
{
char* path[] = { "/bin/sh", NULL };
int err = execve(path[0], path, NULL);
printf("%d\n", err);
printf("%s\n", strerror(errno));
printf("%p, %p\n", path, &path);
return 0;
}