|
|
Log in / Subscribe / Register

Handling argc==0 in the kernel

Handling argc==0 in the kernel

Posted Jan 28, 2022 20:06 UTC (Fri) by dskoll (subscriber, #1630)
In reply to: Handling argc==0 in the kernel by flussence
Parent article: Handling argc==0 in the kernel

You don't need to muck about in /proc. The first argument to execve() is the pathname being executed; that could be placed as argv[0].


to post comments

Handling argc==0 in the kernel

Posted Jan 28, 2022 20:20 UTC (Fri) by matthias (subscriber, #94967) [Link] (1 responses)

Why not just pass "", i.e. the empty string?

If a callee does not inspect argv[0], then any string is good. If a callee expects some non-empty string as argv[0], then calling with argv pointing to { NULL } does not work today. And there is no reason why it should work tomorrow. Doing anything else than aborting with an error would only be to be backwards compatible with the current situation.

The only reason this could break anything that is working now that I can images is, that some callee actually expects to be called with argc==0 and argv pointing to { NULL }. But this would be really weird.

Handling argc==0 in the kernel

Posted Jan 30, 2022 21:43 UTC (Sun) by developer122 (guest, #152928) [Link]

You could run into issues with programs that check argc. They may expect it to be zero, or they may expect it to be 1 with a valid path, but they may not expect it to be 1 with an invalid path.

Handling argc==0 in the kernel

Posted Jan 28, 2022 20:24 UTC (Fri) by khim (subscriber, #9252) [Link] (4 responses)

Nope. It couldn't. Since that one, too, may be /proc/self/exe (and, indeed there are one case where pattern exec("/proc/self/exe", NULL, NULL); is used).

So it's not bullet-proof and, I think, few examples where this Linux-only misfeature is exploited are not worth inventing crazy schemes.

Handling argc==0 in the kernel

Posted Jan 28, 2022 21:07 UTC (Fri) by dskoll (subscriber, #1630) [Link] (3 responses)

But if execve("/proc/self/exe", NULL, NULL); succeeds, under what circumstances could /proc/self/exe not be relied on in the execed program?

Handling argc==0 in the kernel

Posted Jan 28, 2022 21:15 UTC (Fri) by khim (subscriber, #9252) [Link] (2 responses)

When someone would call `realpath` on it? That never happened in real-world usecase so yeah, you are right, that may a way out.

Of course this would also break most tests anyway thus it's not clear if couple of real programs are worth that complexity.

Kernel config option looks more and more sensible: we know such programs are rare, but how rare exactly?

Handling argc==0 in the kernel

Posted Jan 28, 2022 21:26 UTC (Fri) by dskoll (subscriber, #1630) [Link] (1 responses)

realpath is an executable; I think you meant readlink(2). But my point is this: If the original execve call succeeds, then "/proc/self/exe" must still be valid in the exec'd program. if /proc/self/exe were not valid, then the execve call would fail.

Handling argc==0 in the kernel

Posted Jan 29, 2022 2:48 UTC (Sat) by comex (subscriber, #71521) [Link]

Not to get lost in the weeds, but realpath is also the name of a function; see `man 3 realpath`.

Handling argc==0 in the kernel

Posted Jan 28, 2022 20:31 UTC (Fri) by floppus (guest, #137245) [Link] (7 responses)

But if any setuid program actually relies on argv[0] being the name of the program, that's a severe bug (symlinks, TOCTOU, etc., never mind the fact that the caller can always specify any string they want.)

If the kernel were to silently replace argc==0 with argc==1, it seems like using an empty string would be most parsimonious. At least an empty string is guaranteed not to be a valid filename, whereas /proc/self/exe or the name of the executable might or might not be.

Handling argc==0 in the kernel

Posted Jan 28, 2022 21:11 UTC (Fri) by dskoll (subscriber, #1630) [Link]

I think either an empty string or a copy of the first argument to execve is a good choice.

Handling argc==0 in the kernel

Posted Jan 28, 2022 21:21 UTC (Fri) by khim (subscriber, #9252) [Link] (3 responses)

> But if any setuid program actually relies on argv[0] being the name of the program, that's a severe bug (symlinks, TOCTOU, etc., never mind the fact that the caller can always specify any string they want.)

How? All examples I have ever saw are using argv[0] only to multiplex binaries. They don't ever look on the actual binary which is specified in argv[0], rather, they are only interested in `basename`. Symlinks, TOCTOU and even the fact that caller can specify anything there are irrelevant: for them it's just an argument of the command line which happen to include name of the program.

And empty arguments have tendency to make programs wonky.

Handling argc==0 in the kernel

Posted Jan 28, 2022 22:12 UTC (Fri) by NYKevin (subscriber, #129325) [Link] (2 responses)

> And empty arguments have tendency to make programs wonky.

setuid programs already need to defend against argv[0] == "" (or any other actual string, for that matter) because they must not trust the caller. POSIX explicitly specifies that the caller can set argv[0] to whatever it wants, and passing an invalid or incorrect argv[0] has been well understood for a long time as A Thing That Can Be Done (even though it's probably a bad idea in most cases). OTOH, the "there is no argv[0]" case is much less obvious and (I think) is not supported at all on some platforms, so it should not be too surprising that at least one setuid program failed to check for it.

So, from a security perspective, changing "the string doesn't exist" to "the string is empty" is the most straightforward way to close the security hole, since the callee is very likely already checking for an empty string (to the extent that it cares about argv[0] at all).

Handling argc==0 in the kernel

Posted Jan 28, 2022 22:41 UTC (Fri) by JoeBuck (subscriber, #2330) [Link]

Replacing argv[0] via an exec call was a common trick back in the days of students sharing some Vax machine and wanting to hide the fact that they were playing games from "ps".

Handling argc==0 in the kernel

Posted Feb 10, 2022 4:45 UTC (Thu) by rlhamil (guest, #6472) [Link]

And arguments against altering argv in the kernel don't make sense, since that already happens for interpreter execs, right?

That's a much more complex transformation than inserting argv[0]="" if argv is NULL or argv[0] is NULL.

Handling argc==0 in the kernel

Posted Jan 30, 2022 21:48 UTC (Sun) by developer122 (guest, #152928) [Link] (1 responses)

I think changing argc from 0 to 1 and adding an empty string will probably trip up legitimate programs. If argc is 0, then they may handle that by not checking argv and all is well. If argc is one, then they may expect a valid entry in argv[0]. It's still not great to require a valid name in argv[0], but regardless of what vulnerabilities may exist already I can see this causing more breakage to programs that attempt to handle argc==0 correctly.

Handling argc==0 in the kernel

Posted Feb 1, 2022 1:37 UTC (Tue) by NYKevin (subscriber, #129325) [Link]

As I explained in another comment, the caller can set argv[0] to any string it wishes, and a setuid program must not trust the caller (because the caller is unprivileged). So all setuid programs *must* behave correctly for invalid or "wrong" argv[0]. If they don't, then that's a separate vulnerability which must be fixed regardless of what the kernel does in the argc == 0 case. By coalescing the two cases into one case, you halve the number of potential vulnerabilities that application writers need to worry about.

Handling argc==0 in the kernel

Posted Feb 4, 2022 16:48 UTC (Fri) by sbaugh (guest, #103291) [Link] (2 responses)

>The first argument to execve() is the pathname being executed; that could be placed as argv[0].

Not when using execveat(fd, "", ..., AT_EMPTY_PATH)

Handling argc==0 in the kernel

Posted Feb 4, 2022 17:04 UTC (Fri) by adobriyan (guest, #30858) [Link]

d_path() can name any file.

Handling argc==0 in the kernel

Posted Feb 5, 2022 1:14 UTC (Sat) by mchapman (subscriber, #66589) [Link]

What is the process name -- as returned by prctl(PR_GET_NAME) -- when you do that? It seems like whatever it chooses would be an appropriate thing to default argv[0] to.


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds