[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox-cvs
Subject:    [Bug 15481] New: /bin/sh does not work when invoked with argv[0] different from "sh"
From:       bugzilla () busybox ! net
Date:       2023-03-22 16:01:03
Message-ID: bug-15481-161 () https ! bugs ! busybox ! net/
[Download RAW message or body]

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@busybox.net
          Reporter: lersek@redhat.com
                CC: busybox-cvs@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.
_______________________________________________
busybox-cvs mailing list
busybox-cvs@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox-cvs
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic