Bug 30262 - execvp() disobeys POSIX requirement on preserving $0 to script
Summary: execvp() disobeys POSIX requirement on preserving $0 to script
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.39
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2023-03-22 20:35 UTC by Eric Blake
Modified: 2023-05-12 15:17 UTC (History)
2 users (show)

See Also:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Eric Blake 2023-03-22 20:35:07 UTC
Ever since glibc first implemented ENOEXEC fallback to the shell execution of a script (see commits 6a032d81 and a1c46301bb back in 1996), it has passed "/bin/sh" (well, _PATH_BSHELL) as the argv[0] of the new shell process, which loses out on the original argv[0] of the exec[lv]p() caller.  Current POSIX wording says this is wrong; and in fact, FreeBSD updated their libc in 2020 to fix the same compliance bug:
and since they didn't get a lot of complaints, at least the BSD world didn't have too many scripts where the change in $0 from "sh" to the original filename in an ENOEXEC fallback mattered in practice.

However, I will also point out that passing argv[0] unchanged breaks busybox sh (see https://bugs.busybox.net/show_bug.cgi?id=15481).  If the intent is to provide a known $0 to the shell script, the as-if rule may let us get by with other means for passing "sh" as argv[0] to the shell but still giving the shell enough information to set $0.

The as-if rule might let us use ("/bin/sh", "sh", "-c", ". quoted_filename", argv[0], ...) or ("/bin/sh", "sh", "-c", "exec -a \"$0\" quoted_filename \"$@\"", argv[0], ...) if we want to avoid breaking systems where /bin/sh is busybox, but still get $0 set to the POSIX-mandated name.  (The former has issues on sh where . parses files as a compound_command rather than a program - yes, the difference is observable when it comes to alias handling; the latter has problems on sh where 'exec -a' is not implemented, since POSIX doesn't mandate it).

I've opened a bug with the Austin Group seeing if they will relax the standard to allow our behavior of passing "sh" rather than arg0 when hitting the ENOEXEC fallback (note that because of kernel handling of #! lines, and most scripts being installed with a shebang, it is surprisingly rare that glibc even sees ENOEXEC in the first place):

It's probably worth waiting for the Austin Group conversation to settle before we decide which change (if any) is needed, given that unlike the FreeBSD world, we really do risk breaking systems where /bin/sh is from busybox.
Comment 1 Eric Blake 2023-05-12 15:17:03 UTC
It turns out the POSIX folks agree that the wording was too strict, and they intend to change things to permit glibc behavior as compliant by default:

We can probably close this as not a bug given that POSIX is fixing theirs; although we may still want a patch that documents that we EXPLICITLY choose to pass something ending in basename "sh" as argv[0] during shell fallback precisely because /bin/sh may be busybox that depends on argv[0]'s contents, while the shell script's $0 is unaffected by what we put there.