> And "control a directory" is weasel words;
I did not choose the term to confuse you, that's from the definition document linked to the CVE:
https://cwe.mitre.org/data/definitions/426.html
The CVE itself uses the language "If the NEWROOT is writable by an attacker" which could refer to a shared library (as indicated in the report), or even a passwd file as would have been true since the origin of chroot()
> root technically controls everything in one sense of the word.
But not the sense we're talking about.
> Because you can't call chroot(2) unless you're root
Well you can[1], but this is /usr/sbin/chroot aka chroot(8) when used with a non-numeric --userspec, and the point is to drop root to a user that root controls with setuid(2). Something needs to map user names to the numeric userids that setuid(2) uses, and that something is typically the NSS database.
Now: Which database should be used to map a username to a userid?
- The one from before the chroot(2)?
- Or the one that you're chroot(2)ing into
If you're the author of the code in-question, you chose the latter, and that is totally obvious to anyone who can read because that's the order the code appears in, but it's also obvious that only the first one* is under control of root, and so only the first one could be correct.
[1]: if you're curious: unshare(CLONE_USERNS|CLONE_FS) can be used. this is part of how rootless containers work.
Joker_vD
today at 11:45 AM
> Well you can[1],
No, you can't, it's an entirely different syscall that does something vaguely similar. IMHO there are a bit too many root-restricted operations that should not have been; but they are, so we're stuck with setuid-enabled "confused deputies" — arguably, it's the root that should be prohibited from calling chroot(2).
> Now: Which database should be used to map a username to a userid? If you're the author of the code in-question, you chose the latter
That's the problem: the choice is implicit. If the author moved setuid/setgid calls way up in the call order, the implicit choice would've also been the safe one but it was literally impossible.
> unshare(CLONE_USERNS|CLONE_FS) can be used
Wait, CLONE_USERNS? That's not a real flag. Did you mean CLONE_NEWUSER?