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

Attachment: pgpE5ro7uSfVy.pgp
Description: OpenPGP digital signature

Reply via email to