为什么 execve 系统可以在没有任何 argv 参数的情况下调用 运行“/bin/sh”,但不能调用“/bin/ls”?
Why can the execve system call run "/bin/sh" without any argv arguments, but not "/bin/ls"?
我对 __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"
执行失败?
这不是内核问题。内核将 运行 与 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]
。这就是 运行 没有问题的原因。
参考源码:
我对 __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"
执行失败?
这不是内核问题。内核将 运行 与 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]
。这就是 运行 没有问题的原因。
参考源码: