Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aR31ST3FzOB7xS7e@intrepid>
Date: Wed, 19 Nov 2025 17:50:17 +0100
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Cc: Mike Hilgendorf <mike@...gram.dev>
Subject: Re: `unsetenv()` does not always work when run in an
 `__attribute__((constructor))` function

Hi all,

it's been a while since this thread, but I still want to get back to it:
Is it sensible to pass __environ as third argument to main(), rather
than the original envp?

Reason I ask is that I recently checked out what the current POSIX says
about this third argument, and I found it doesn't say anything at all.
According to POSIX, this argument is a pure extension. So basically, we
can do what we want there. I seem to remember that earlier versions had
something to say about it, though, but it has been dropped from the
current description of exec().

Then I also checked out the bad actor in this thread, namely bash. I
wondered whether they are somehow testing for the presence of the third
arg. I struggle to think of a way to do so, however. If the third arg is
not given, then declaring one will in practice give garbage values that
can be anything. And there is absolutely no way to detect this before
runtime, making it a poor option for configure testing, since it isn't
cross-compilation compatible.

But anyway, what bash is doing is just detecting the platforms it knows
not to give that argument (namely OpenNT and MVS), and then it adds the
macro to switch the behavior to the command line. And in the code
itself, while it uses the NO_MAIN_ENV_ARG macro to select the behavior
in two places, in a third it just uses the platform macros directly. So
this whole thing just doesn't work if any implementation ever decides to
change its behavior (e.g. to align with POSIX).

Anyway, back to musl: Since it is currently giving a third arg to main,
stopping doing so would be an ABI breakage. But nobody said the third
argument has to be the original envp. If we pass __environ instead, then
the effects of constructors modifying the environment will show up in
main(). And __environ is definitely a valid environment (i.e. a vector
of pointers to strings, each being of the form "key=value"). So there's
no violation of any expectations.

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.