On Mon, 05 Oct 2026 21:09:31 -0700 Collin Funk <[email protected]> wrote:
> 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. Yeah, my suggested flag name was due to a mixup on my end. I thought the --no-canonicalize option of 'mount' did what I wanted but for the 'mount' command when I started composing the email, learned I was mistaken before sending it, and then didn't think to change my suggested option name when I hit send. Maybe just ripping off the openat2 flag name and calling it --resolve-no-symlinks would work? -- Aaron > Collin > > [1] https://man7.org/linux/man-pages/man2/openat2.2.html
pgpE5ro7uSfVy.pgp
Description: OpenPGP digital signature
