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

Reply via email to