I am confused with the syscall of __NR_execve
. When I learn linux system call. The correct way that I know to use execve
is like this:
char *sc[2];
sc[0]="/bin/sh";
sc[1]= NULL;
execve(sc[0],sc,NULL);
Then the function execve
will call syscall()
to get into system kernel with putting the arguments on Registers EAX
, EBX
, ECX
and EDX
. However, It still succeed if I use
execve("/bin/sh",NULL,NULL);
But if I replace "/bin/sh"
with "/bin/ls"
,it fail with:
A NULL argv[0] was passed through an exec system call.
I wonder why "/bin/sh"
can be executed successfully without enough parameters while "/bin/ls"
fail?
This is not a kernel issues, kernel will run filename
arg of execve regardless of argv
and envp
are NULL
or not, it is just a unix convention that argv[0]
points to the program name.
And what's you saw is just normal, nothing is wrong. Because ls
is part of GNU's coreutils, and all programs in the coreutils package call set_program_name
to do some setup work, you can see in the source, it checks whether argv[0]
if NULL, and it will call abort
when it is.
On the other hand, /bin/sh
is apparently a program that does not belong to coreutils, and does not check against argv[0]
, that's why it run without the problem.
Refer to the source code:
http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c#n1285
http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/progname.c#n51