[Bug 15481] New: /bin/sh does not work when invoked with argv[0] different from "sh"

bugzilla at busybox.net bugzilla at busybox.net
Wed Mar 22 16:01:03 UTC 2023


https://bugs.busybox.net/show_bug.cgi?id=15481

            Bug ID: 15481
           Summary: /bin/sh does not work when invoked with argv[0]
                    different from "sh"
           Product: Busybox
           Version: 1.35.x
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P5
         Component: Standard Compliance
          Assignee: unassigned at busybox.net
          Reporter: lersek at redhat.com
                CC: busybox-cvs at busybox.net
  Target Milestone: ---

The POSIX specification (Issue 7, TC2 applied) explains at

  https://pubs.opengroup.org/onlinepubs/9699919799/functions/execvp.html

that, if

  execvp(file, { argv[0], argv[1], ..., NULL })

were to fail with -1/ENOEXEC, then execvp() must retry "as if" with

  execv(<shell path>, { argv[0], file, argv[1], ..., NULL })

In other words, if direct execution of "file" failed because "file" "has the
appropriate access permission but has an unrecognized format", then execvp() is
required to try executing "file" as a shell script. For that, <shell path> is
left unspecified by POSIX, but the arguments of the shell are specified:

- Argv[0] remains the same. That is, what we wanted "file" to know itself as,
is what we now want *the shell executable* to know itself as.

- argv[1] becomes "file" -- this is the script that the shell is supposed to
run.

- argv[2] and onwards become positional parameters $1, $2, ... for the shell
script.

On a system where "/bin/sh" is provided by busybox (that is, "/bin/sh" is a
symlink to "/bin/busybox"), any execvp() implementation that uses "/bin/sh" for
<shell path> will break the required ENOEXEC behavior, in the general case.
That's because busybox will not recognize from argv[0] (= file) that it's
supposed to behave as the shell.

The simplest way to demonstrate the bug is this:

bash$ ( exec -a foobar /bin/sh <<< "echo hello" )
foobar: applet not found

(Unfortunately, the bug cannot be demonstrated via widely used C libraries,
such as glibc and musl. The reason is that *both* glibc and musl have bugs that
*hide* the busybox bug.

- In musl, the ENOEXEC path is not handled at all, so musl doesn't even try to
invoke the shell.

- In glibc, the POSIX-mandated argument list for the shell is not implemented
properly. Again, the argument list is supposed to be

  execv(<shell path>, { argv[0], file, argv[1], ..., NULL })

but glibc does

  execv(<shell path>, { <shell path>, file, argv[1], ..., NULL })

which is precisely what masks this busybox bug.

Refer to _PATH_BSHELL in historical glibc commit 6a032d815819, and in today's
glibc file "posix/execvpe.c".)

The ask here is to provide a standalone /bin/sh binary that is not sensitive to
what argv[0] it is invoked under. Thanks.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the busybox-cvs mailing list