tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Proposal: getexecpath(3)



On Sun, Jan 05, 2025 at 04:24:23AM +0100, Jean-Yves Migeon (NetBSD) wrote:
 > > Under normal circumstances the callee can use argv[0], though
 > > admittedly it's a bit of a nuisance since it requires examining $PATH
 > > if there's no / in the string. One could certainly make a library
 > > function that does that though.
 > 
 > argv[0] (by C99) is just program's name, and has no warranty of
 > representing (even a substring of) the exec path; and has its use in that
 > regard, e.g. crunchgen(1). Reliably deducing the exec path from argv[0] is
 > tricky. getexecpath(3) would have no ambiguity on its semantic.

We're not talking about C99, or the provisions in C99 for MS-DOS and
Windows; we're talking about Unix and specifically NetBSD. I think you
missed the part where I wrote:

 > > This is a matter of the conventions of shells

For the sake of argument, I wrote the code, stuck it in /usr/local/bin,
and ran it in various ways, first from sh:

$ hey
my path: /usr/local/bin/hey
$ /usr/local/bin/hey
my path: /usr/local/bin/hey
$ PATH=.:$PATH hey
my path: /usr/local/bin/hey
$ (cd /usr/local/bin && PATH=.:$PATH hey)
my path: ./hey
$ (cd /usr/local/bin && PATH=$PATH:. hey)
my path: /usr/local/bin/hey
$ (cd /usr/local/bin && PATH=. hey)
my path: ./hey
$ (cd /usr/local/bin && PATH= hey)
my path: ./hey
$ (cd /usr/bin && PATH= hey)
sh: hey: not found

which is correct in all cases. Then I ran the same cases again from
ksh, bash, zsh, csh, and tcsh, all of which gave the same results.

This should not come as a surprise; shells work this way by
long-standing convention.

 > Also all argv[] strings can be modifiable by callee. pathname of the
 > execution (as passed to execve(2) or like) is not.

So?

(also, that's UB in C so the traditional Unix behavior is not by any
means guaranteed, and on NetBSD you should be using setproctitle(3)
for that instead anyhow)

 > > It is reasonable to fail if the caller passes trash in argv[0].
 > 
 > I agree as long as it is gracefully done. *argv contains
 > implementation-defined values. So would be its failure modes when dealing
 > with garbage.

I don't see the problem here. If you screw with it, it'll produce
wrong answers. So will, to varying degrees, all other techniques. As
already noted, none of them are suitable for security perimeters.

 > > The only cases where this isn't true are setugid bins, where argv[0]
 > > might be malicious, and these cases shouldn't be using any of the
 > > other referenced mechanisms either as most of them are subject to
 > > races or other interference.
 > 
 > Pretty much "any" binary, not just setugid.

No?

 > Any binary that is subject to confused deputy problem can be. If you
 > consider the "traditional" user's security boundary, CGI binaries are good
 > examples. The environment is partially controllable by a "less-privileged"
 > caller and can affect multiple users.

...which lets an adversary set argv[0] how?

 > Now TBH even a "standard" program that fails miserably argv handling and
 > wreaks havoc as a normal user would still be very painful. See, I would not
 > like /rescue/cat to act as /rescue/rm, even if it is not setugid (:

If you go to the trouble of explicitly calling it as rm, it'll do what
you asked. Why you would do that when you can just as easily run
/rescue/rm or /bin/rm, IDK.

Likewise you could certainly start qemu or some other program that
wants to use this technique to get its install prefix, and
intentionally lie to it so it doesn't run or crashes trying to find
its initialization files. But what's the point? And again, you can do
this with all the proposed techniques.

The question is whether it works as expected under normal conditions,
and it does.

-- 
David A. Holland
dholland%netbsd.org@localhost


Home | Main Index | Thread Index | Old Index