Re: [PATCH RFC 4/7] fs: support FD_FAILFS_ROOT in fchroot()

Andy Lutomirski <[email protected]> Thu, 23 Jul 2026 09:59:52 -0700
Newsgroups org.kernel.vger.linux-api,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel
Message-ID <CALCETrW-ObgCm=Vhm6AiyyS25q+SyXkCvVWB7JEaawmOMCrrpA@mail.gmail.com>
On Thu, Jul 23, 2026 at 7:49=E2=80=AFAM Christian Brauner <[email protected]=
rg> wrote:
>
> On 2026-07-23 06:50 -0700, Andy Lutomirski wrote:
> > On Thu, Jul 23, 2026 at 6:09=E2=80=AFAM Christian Brauner <brauner@kern=
el.org> wrote:
> > >
> > > On Thu, Jul 23, 2026 at 05:49:06AM -0700, Andy Lutomirski wrote:
> > > > On Thu, Jul 23, 2026 at 4:37=E2=80=AFAM Christian Brauner <brauner@=
kernel.org> wrote:
> > > > >
> > > > > Once entered, failfs is a throw-away-the-key moment. The task is
> > > > > considered chrooted so it cannot create user namespaces to regain
> > > > > CAP_SYS_CHROOT. chroot()/fchroot() back out require CAP_SYS_CHROO=
T.
> > > >
> > > > I kind of alluded to this earlier, but I don't think we should prom=
ise
> > > > this.  In particular, I still think we should eventually allow a
> > > > non-chrooted process with no_new_privs to chroot to any valid
> > > > directory, and I think we should consider changing the definition o=
f
> > > > current_chrooted() such that failfs-as-root would cause it to retur=
n
> > > > false.  I'm also not sure why it's useful -- if I want to throw awa=
y
> > >
> > > I had considered that but introducing this change alongside this seri=
es
> > > felt too spicy for me.
> >
> > I think I agree.  My only actual objection to your series as is is
> > that your wording seems to make a promise that I think shouldn't be
> > made.
>
> Agreed.
>
> >
> > >
> > > > the key to accessing the normal contents of my mountns without
> > > > changing my mountns, I need to chroot somewhere (like failfs) *and*=
 I
> > > > need to somehow prevent myself from getting an fd or a magic link b=
ack
> > > > to the ordinary mountns contents.  If I somehow get such an fd,
> > > > preventing my from fchrooting to it doesn't seem to accomplish
> > > > anything, since I could traverse the fd with openat, etc just as
> > > > easily, or even fchdir to it and use relative paths.
> > >
> > > I think I generally agree with you. My main concern here is mostly ab=
out
> > > changing very long-standing behavior here and making failfs special h=
ere
> > > feels like it could easily misused.
> >
> > I don't think either of us are really suggesting making failfs
> > special.  I agree about the long-standing behavior.
> >
> > >
> > > >
> > > > My understanding of the exact workings of the mount tree is possibl=
y
> > > > not good enough to specify the semantics I think are correct quite
> > > > exactly, but I think a decent approximation is that a task should b=
e
> > > > considered to be not chrooted if its root is at the top of its moun=
t
> > > > tree or is not in a mount tree at all.
> > >
> > > If we could altering this definition from the patchset I would be in
> > > favor of it. I'm curious what your take is though.
> > >
> >
> > I can't quite parse your question.
>
> Maybe I should shunt everything I write through an LLM so it catches
> grammatical nonsense.
>
> It was basically just trying to say "let's not redesign
> current_chrooted()" in this series - which I already did above.
>
> > I have three sort-of-concrete proposals:
>
> The best proposals...
>
> > (a) current_chrooted returns false if follow_dotdot starting at
> > current root but with nd->root equal to the namespace root would
> > succeed and return the current root.  I think this is fairly solid.
> > The main caveat I can think of is that someone could create a detached
> > mount tree, chroot to its root, then fork and have the child:
> >
> >  - drop privileges
> >  - set no_new_privs
> >  - chroot somewhere else
> >
> > then the parent or another privileged task mounts that tree somewhere,
> > and the child could now access the parent of the mountpoint.  Any
> > actual exploit based on this seems farfetched.
>
> It would also be easy to prevent unprivileged chroot()ing into detached
> mount trees. They're easy to recognize and it's not a super common
> use-case.

In some sense chrooting into a detached mount tree is an entirely
reasonable operation.  Make your favorite mount tree and chroot there
-- it's like mount-namespaces minus the namespace.