我对__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"
替换"/bin/sh"
,它会失败,并显示:
A NULL argv[0] was passed through an exec system call.
我想知道为什么"/bin/sh"
可以在没有足够参数的情况下成功执行,而"/bin/ls"
却失败了?
这不是内核问题。无论argv
和envp
是否为NULL
,内核都将使用execve
的filename
参数运行。argv[0]
指向程序名称只是Unix的惯例。
你所看到的一切都很正常,也就是说没有什么问题。因为ls
是GNU核心实用程序的一部分,核心实用程序包中的所有程序都调用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