[TUHS] Exec With 0 and NULL argc and argv? (was: the first busybox)

Steffen Nurpmeso via TUHS tuhs at tuhs.org
Fri Oct 23 08:56:53 AEST 2026


segaloco via TUHS wrote in
 <_OVPprIF6oUXZ0dk1mMcrVQLAN8SXMlQYn9EtWUyce5sAkcyHzqTZOGE2Jy-rADX1_wsWaS\
 RarQZg083aIdZHJ_kUDGMRv7HXIxV38e_-lw=@protonmail.com>:
 |On Thursday, October 22nd, 2026 at 15:13, Steffen Nurpmeso via TUHS \
 |<tuhs at tuhs.org> wrote:
 |
 |> Too much honour.  I think we were once there in the past already.
 |> K&R says in "5.10 Command-line Arguments"
 |> 
 |>   By convention, argv[0] is the name by which the program was
 |>   invoked, so argc is at least 1.
 |> 
 |> But in 2021 there was CVE-2021-4034 --- through execve(2) one
 |> could enforce another condition, and that caused quite some
 |> trouble.  Now, if i ask Google AI it says
 |>
 |> [insert AI digest here detailing kernel/execs supporting argc == 0]
 |> ...
 |Ah that all makes a bit more sense...so it's more about various kernels
 |allowing a process to be exec'd without compliant argc/argv passing
 |rather than legitimate situations where it's completely reasonable to
 |expect these to be 0/NULL it seems.  That's what I get from your AI
 |digest anyway.

Yes, but there was quite a turmoil and many programs were hastily
patched.

 |So at the end of the day the problem being solved is the fact that,
 |despite standards committees' best efforts, many kernels and exec
 |mechanisms seem to let you get into this messy state?  I'm just
 |surprised that the solution is yet another call rather than kernels just
 |getting cleaned up to prevent this.  Is there some legitimate reason to
 |exec something and zero out the argument info?  Is the new function
 |added as to not break applications that *do* depend on argc == 0 despite
 |it being recognized as generally bad all around in a hosted environment?

The reason is "quite another", best i quote the issue [1]

  There is currently no standardized, portable mechanism in POSIX
  to retrieve the absolute pathname of the executable file
  currently executing the calling process. Runtimes, language
  interpreters, and asset loaders must resort to highly
  unportable, platform-specific mechanisms.

  - Linux relies on parsing the "/proc/self/exe" symlink or using
    `getauxval(AT_EXECFN)`.
  - FreeBSD and NetBSD use a sysctl interface via KERN_PROC_PATHNAME.
  - SunOS implements getexecname().
  - macOS implements a non-POSIX _NSGetExecutablePath() function.

  Others like OpenBSD force us to rely on argv[0] and (if the
  process didn't start with an absolute path) scanning the PATH
  environment variable, which is fundamentally unsafe and
  unreliable (someone else in the PATH with the same name
  appearing early is picked up). Furthermore, the parent process
  can easily manipulate or empty argv and envp during an execve()
  call, leaving the child completely unable to safely determine
  its own physical location.

  Adding a native, safe API to POSIX eliminates immense
  cross-platform boilerplate across programming frameworks and
  toolchains that require explicit binary path auditing.

However there is chroot(2) and namespaces with mount overlays, or
even entire abstractions like CloudABI[2] was.
As in, "what is a pathname worth".  It was suggested to instead
use something like getauxval(2) (Linux) AT_EXECFD, the file
descriptor of the program.  Maybe getauxval(3) as such would be
the best, there are several items that really make sense for many.

Yet then OpenBSD went ahead and implemented that plain thing, and
mostly got rid of argv[0] in the base system (at least many, many
changes were done by de Raadt), in favour of that thing, doing
kind of basename(3) as necessary first.

  [1] https://www.austingroupbugs.net/view.php?id=1992
  [2] https://lwn.net/Articles/674770/

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)


More information about the TUHS mailing list