[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <2025-11-20-nifty-tied-sables-casualty-AgEHtJ@cyphar.com>
Date: Thu, 20 Nov 2025 20:24:55 +1100
From: Aleksa Sarai <cyphar@...har.com>
To: Demi Marie Obenour <demiobenour@...il.com>
Cc: Alyssa Ross <hi@...ssa.is>, linux-fsdevel@...r.kernel.org,
Jann Horn <jannh@...gle.com>, "Eric W. Biederman" <ebiederm@...ssion.com>, jlayton@...nel.org,
Bruce Fields <bfields@...ldses.org>, Al Viro <viro@...iv.linux.org.uk>, Arnd Bergmann <arnd@...db.de>,
shuah@...nel.org, David Howells <dhowells@...hat.com>,
Andy Lutomirski <luto@...nel.org>, Christian Brauner <brauner@...nel.org>,
Tycho Andersen <tycho@...ho.pizza>, linux-kernel@...r.kernel.org, linux-api@...r.kernel.org
Subject: Re: Safety of resolving untrusted paths with detached mount dirfd
On 2025-11-19, Demi Marie Obenour <demiobenour@...il.com> wrote:
> On 11/19/25 21:18, Aleksa Sarai wrote:
> > On 2025-11-19, Alyssa Ross <hi@...ssa.is> wrote:
> >> Hello,
> >>
> >> As we know, it's not safe to use chroot() for resolving untrusted paths
> >> within some root, as a subdirectory could be moved outside of the
> >> process root while walking the path[1]. On the other hand,
> >> LOOKUP_BENEATH is supposed to be robust against this, and going by [2],
> >> it sounds like resolving with the mount namespace root as dirfd should
> >> also be.
> >>
> >> My question is: would resolving an untrusted path against a detached
> >> mount root dirfd opened with OPEN_TREE_CLONE (not necessarily a
> >> filesystem root) also be expected to be robust against traversal issues?
> >> i.e. can I rely on an untrusted path never resolving to a path that
> >> isn't under the mount root?
> >
> > No, if you hit an absolute symlink or use an absolute path it will
> > resolve to your current->fs->root (mount namespace root or chroot).
> > However, OPEN_TREE_CLONE will stop ".." from naively stepping out of the
> > detached bind-mount. If you are dealing with procfs then magic-links can
> > also jump out.
>
> Is using open_tree_attr() with MOUNT_ATTR_NOSYMFOLLOW enough to prevent
> these? Will it still provide protection even if someone concurrently
> renames one of the files out from under the root? I know that can
> escape a chroot, but I wonder if this provides more guarantees.
That will block symlinks (in a similar manner to RESOLVE_NO_SYMLINKS),
so those particular problems would not be an issue. Of course, a lot of
symlink usages are valid and so this will block those as well (back when
I wrote openat2 I did a cursory scan and something like 15% of system
paths contained symlinks on my system).
I think that ".." will not be a problem even with renames because the
detached mount is associated with the directory (just like how moving a
bind-mount source doesn't suddenly expose more information).
It also goes without saying that you need to make sure an absolute path
*never* gets passed to any of the helper functions you write to do this
-- in my view this is usually going to be quite a fragile setup. Who is
providing the paths to your program?
> https://github.com/QubesOS/qubes-secpack/blob/main/QSBs/qsb-014-2015.txt
> was the chroot breakout.
>
> > You can always use RESOLVE_BENEATH or RESOLVE_IN_ROOT in combination
> > with OPEN_TREE_CLONE.
>
> Unfortunately not everything supports that. For instance, mkdirat()
> doesn't.
You can openat2(RESOLVE_BENEATH) the parent directory and then mkdirat()
the final component (because mkdirat does not follow trailing symlinks).
This is what libpathrs[1] does, and it works for most *at() syscalls
(those that support AT_EMPTY_PATH are even easier).
[1]: https://github.com/cyphar/libpathrs
--
Aleksa Sarai
https://www.cyphar.com/
Download attachment "signature.asc" of type "application/pgp-signature" (266 bytes)
Powered by blists - more mailing lists