Handling argc==0 within the Linux kernel

62
Handling argc==0 within the Linux kernel

Welcome to LWN.fetch

The following subscription-ultimate explain has been made readily available within the market to you
by an LWN subscriber. Hundreds of subscribers rely on LWN for the
ultimate info from the Linux and free tool communities. Ought to you skills this
article, please have in mind of subscribing to LWN. Thank you
for visiting LWN.fetch!

By Jonathan Corbet
January 28, 2022

By now, most readers are liable to have in mind of the Polkit vulnerability identified as CVE-2021-4034.
The fix for Polkit is barely easy and is being rolled out
at some level of the fetch. The muse of this venture, though, lies in a
misunderstanding about how capabilities are flee on Unix-enjoy systems. This
venture is extremely liable to exist in varied capabilities, so it’d be glorious to
glean a extra fashionable solution. The actual operate to tackle this impart also can merely be
within the kernel, however properly working around this
misunderstanding without causing regressions is now no longer a straightforward job.

I could per chance retract to enjoy an argument, please

Most developers are mindful of the prototype of the predominant program as
expressed within the CΒ language:

    int predominant(int argc, char *argv[], char *envp[]);

The program is invoked with its teach-line arguments in argv and
the atmosphere in envp; both are solutions that could per chance null-terminated
arrays of
charΒ * strings. The option of non-null entries in
argv is kept in argc. This API is an person-operate
advent, though; what happens when the kernel first runs a program is a
dinky bit varied: on Linux, that program is passed a single pointer to the
argv array. The envp array begins straight after the
NULL worth that terminates argv. Thus, in a C program,
the following statement will be correct on entry to predominant():

    envp == argv + argc + 1

By conference, argv[0] is the name of the program that is being
accomplished, and quite loads of capabilities rely on that conference. Because it happens,
though, this conference is exactly that: a conference, however now no longer a guarantee.
The accurate contents of argv are fully below the shield watch over of
whoever calls execve()
to flee the program within the predominant operate, and that caller is now no longer required to
assign the program name in argv[0].

Certainly, the caller is now no longer required to accept as true with argv[0] at all. If
the argv array passed to execve() is empty (or the
argv pointer is merely NULL), the predominant pointer within the
original program’s argv array will be NULL,
and the envp array will originate straight thereafter.
Unfortunately, Polkit (or, extra specifically, the setuid pkexec utility)
“knew” that argv[0] would always be contemporary,
so it carried out its argument processing by iterating over the argv
array initiating at argv[1]. If there are now no longer any arguments at all,
argv[1] is the identical as envp, so pkexec modified into iterating
thru its atmosphere variables as a change. Throw in some in-operate argument
modification (pkexec overwrites its argv array), and
pkexec also can merely be overjoyed to rewrite its atmosphere
variables, thus bypassing the sanitizing of these variables carried out for setuid
capabilities. At that level, the sport modified into over.

This venture is now no longer original, and neither is awareness of it. Ryan Mallon wrote about
it in 2013, noting that “it does enable for some silly behaviour
from setuid binaries
“; he additionally evidently despatched a Polkit
patch to tackle it, however that patch modified into by no attain applied. Even extra
support, in 2007, Michael Kerrisk reported the
kernel’s habits as a bug, however the portray modified into closed with dinky
dialogue. So the venture persisted, culminating within the vulnerability
administrators are scrambling to patch now.

Against a extra fashionable fix

Fixing this impart is an extraordinarily easy topic of making pkexec evaluate that
argc is no much less than one. But there are certainly varied capabilities out
there containing an identical assumptions. Given the energy of the
argv[0] conference, it’s pure to ask whether or now no longer it’s a ways wise to
enable capabilities to be flee with an empty argv array at all. More than likely
it doesn’t, however the contemporary API has quite loads of history and can’t be modified
without quite loads of idea.

Ariadne Conill started
the linux-kernel dialogue with a patch that could per chance merely disallow
calls to execve() without no much less than one argv entry.
Offending callers would obtain an EFAULT return worth as a change. This is in a position to
resolve the venture by offering a guarantee that argv would now no longer be
empty, however at the doable price of introducing complications of its enjoy.
One is that, as Kees Cook realized,
there could be ceaselessly an even quantity of code available within the market that calls
execve() with an empty argv array. Conill wrote
these off as “lazily-written test cases which must be
mounted
“, however regressions in lazily-written test cases are easy
regressions. Moreover, as Heikki
Kallasjoki and Filthy rich
Felker both pointed out, an empty argv array is ceaselessly
allowed by the POSIX long-established.

Felker additionally suggested an different with much less doable for regressions:
ultimate implement a non-empty argv at privilege boundaries β€” when
execve() is being known as to flee a setuid program, in varied words.
Cook acknowledged
that he would rather dwell a ways from taking the privilege boundary into yarn if
which which that you just can assume, though.
He proposed a
varied solution to the venture: inject an additional null pointer at the
terminate of an empty argv array so that even code that tries to skip
argv[0] will survey that there could be nothing there. This solution
won’t work both, as it turns out: the ABI promise is that envp starts
straight after argv, and the extra NULL breaks that
promise. There are evidently capabilities that rely on that structure and would
smash if it were modified.

But one more attain, first suggested
by Eric Biederman, could per chance be to substitute an empty argv with one
containing a single pointer to an empty string. This proposal had some
strengthen (though no one has implemented it as of this writing), however additionally
provoked some worries of its enjoy. More than likely there are capabilities available within the market
that can answer badly to an empty-string argument, or which effect something
special when argc is zero. Altering the option of arguments
passed to the program flee by execve() correct looks to be enjoy it could maybe per chance
create surprises.

Cook at last summarized the
impart this attain:

Given the code we’ve found that is reckoning on NULL argv, I mediate we
likely cannot obtain the alternate outright, so we’re down this uncommon
rabbit gap of making an strive to reject what we are in a position to and create work-around
behaviors for the cases that for the time being exist.

That however, he then went on to particular a preference for the
preliminary alternate (merely
disallowing a nil-argument execve() call anyway, albeit with an
EINVAL return in preference to EFAULT), with an provide to
fix a Valgrind test that is already
identified to interrupt with that restriction.

Conill replied with
a brand original model of the contemporary patch; this time it emits a warning
before failing an empty-argv call to execve() with
EINVAL. Cook acked the
patch, announcing: “Let’s effect it and watch what breaks“; Biederman
concurred:
Especially since you are signing as a lot as succor fix the tests“.

That is where the dialogue stands as of this writing, however it’s a ways from
certain that here is how the venture will at last be addressed. This
patch has, crucially, now no longer but survived its first come upon with Linus
Torvalds, who also can merely take a unlit ask of its doable for regressions. It
is an ABI alternate, as a minimum, and there also can merely neatly be code available within the market
that responds badly to it, though the reality that BSD systems already
restrict an empty argv will, with very top fortune, enjoy already shaken out
most of these.
Ought to easy miserable regressions come up anyway, a clear
solution will nearly certainly must be found.




(Log in to post feedback)

NOW WITH OVER +8500 USERS. folks can Be a part of Knowasiak for gratis. Set aside in on Knowasiak.com
Read More

Knowasiak
WRITTEN BY

Knowasiak

Hey! look, i give tutorials to all my users and i help them!

you're currently offline