我对__NR_execve
的系统调用感到困惑。 当我学习linux系统调用。 我知道使用execve
的正确方法是这样的:
char *sc[2]; sc[0]="/bin/sh"; sc[1]= NULL; execve(sc[0],sc,NULL);
然后函数execve
将调用syscall()
进入系统内核,将参数放在寄存器EAX
, EBX
, ECX
和EDX
。 但是,如果我使用它仍然成功
execve("/bin/sh",NULL,NULL);
但是,如果我用"/bin/ls"
replace"/bin/sh"
"/bin/ls"
,则失败:
A NULL argv[0] was passed through an exec system call.
我想知道为什么"/bin/sh"
可以在没有足够的参数的情况下成功执行,而"/bin/ls"
失败呢?
这不是内核问题,内核会运行execve的filename
arg而不管argv
和envp
是否为NULL
,这只是argv[0]
指向程序名的unix惯例。
你看到的是正常的,没有什么是错的。 由于ls
是GNU的coreutils的一部分,并且coreutils包中的所有程序都调用set_program_name
来做一些设置工作,所以在源代码中可以看到argv[0]
是否为NULL,如果是NULL,则会调用abort
。 另一方面, /bin/sh
显然是一个不属于coreutils的程序,不会检查argv[0]
,这就是为什么它没有问题。
参考源代码:
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