c语言 - 为什么execve系统调用可以在没有任何argv参数的情况下"/bin/sh"运行,但不能"/bin/ls"?



我对__NR_execve的系统调用感到困惑。当我学习linux系统调用时。我知道使用execve的正确方法是这样的:

char *sc[2]; 
sc[0]="/bin/sh"; 
sc[1]= NULL; 
execve(sc[0],sc,NULL); 

然后函数execve将调用syscall()进入系统内核,并将参数放在寄存器EAXEBXECXEDX上。然而,如果我使用,它仍然成功

execve("/bin/sh",NULL,NULL);

但如果我用"/bin/ls"替换"/bin/sh",它会失败,并显示:

A NULL argv[0] was passed through an exec system call.

我想知道为什么"/bin/sh"可以在没有足够参数的情况下成功执行,而"/bin/ls"却失败了?

这不是内核问题。无论argvenvp是否为NULL,内核都将使用execvefilename参数运行。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

最新更新