Hi Aaron, Aaron Rainbolt <[email protected]> writes:
> I occasionally run into a situation where I need a root-owned > script to change the ownership or permissions of a file or directory > located in a directory that is accessible by an unprivileged user. This > requires some tricky work to do safely, since the user could create a > symlink where I expect there to be a directory, pointing at some > sensitive file or directory. This can be worked around in some > situations by checking for symlinks first if the script runs during > early boot where TOCTOU isn't an issue, or passing --no-dereference, > but that doesn't help if I have to dig into a directory that itself may > be a symlink. For instance, if I want to do: > > chown user:user -- /home/user/path/to/dir > > There is no way to do this safely in-place. I can't use setpriv to drop > privileges since chown requires root. I can't check if /home/user/path, > /home/user/path/to, and /home/user/path/to/dir are symlinks first > because that leaves a TOCTOU vulnerability. --no-dereference doesn't > work because chown will dig through the 'path' and 'to' dirs which may > be symlinks to something important. There are ugly ways around this > like copying 'dir' somewhere else, fixing ownership, then deleting the > original and moving the fixed version back, but that's obviously > non-ideal. > > Would it be possible to add a `--no-canonicalize` feature to `chown` > and `chmod` (and possibly other utilities where it might make sense) > that throws an error if any portion of the path being acted on does not > exist or goes through a symlink? My first instinct was to say that this would be too expensive since you would need to open each directory component separately from the root with O_NOFOLLOW. However, I think using openat2 with the RESOLVE_NO_SYMLINKS flag would do the trick without that performance penalty, on top of being safer [1]. I'd need to think about it more before being in favor of it. I think the name '--no-canonicalize' might be a bit confusing, though. It makes me think of path canonicalization, at least, which 'chown' doesn't do (as far as I remember). But the naming is tricky since '--no-dereference' is already used, of course. Collin [1] https://man7.org/linux/man-pages/man2/openat2.2.html
