Why can the execve system call run "/bin/sh" without any argv arguments, but not "/bin/ls"?

10,428

This is not a kernel issue. The kernel will run with the filename arg of execve regardless of whether argv and envp are NULL or not. It is just a Unix convention that argv[0] points to the program name.

And what you saw is just normal, i.e. 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 this in the source: it checks whether argv[0] is 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 runs without the problem.

Refer to the source code:

Share:
10,428
Arvin Hsu
Author by

Arvin Hsu

Updated on June 12, 2022

Comments

  • Arvin Hsu
    Arvin Hsu almost 2 years

    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?

  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com about 7 years
    And here is a minimal example without any argv: stackoverflow.com/a/42290873/895245