Re: [PATCH 0/5] capabilities: close the ways around the CAP_SETFCAP rule for uid 0

From: Christian Brauner

Date: Fri Oct 09 2026 - 03:42:28 EST


On Thu, Oct 08, 2026 at 11:13:57AM -0500, Serge Hallyn wrote:
> On Thu, Oct 08, 2026 at 03:39:30PM +0000, Josef Bacik wrote:
> > On Thu, Oct 08, 2026 at 08:57:56AM -0500, Serge E. Hallyn wrote:
> > > Would you mind describing what other solutions you considered? I've been
> > > looking over this set since Tuesday, and finding it hard to reason about.
> > > (Part of that is certainly the nature of the problem, and it's possible
> > > that this is the best/simplest solution.)
> >
> > Everything we looked at kept the state in the cred. We model checked
> > the variants before writing the code, and these fell over:
> >
> > - a bool per cred for "had CAP_SETFCAP over the parent when it entered".
> > It breaks on two hops: setns() into a namespace that maps 0, unshare
> > again, and the bool says yes for the second namespace. Hence the
> > level.
> > - checking only at uid_map write time. That misses setxattr of
> > security.capability in a namespace that already maps 0, hence patch 4.
> >
> > We didn't look at keeping the state on the namespace.
> >
> > > If we replaced the userns->parent_could_setfcap bool with a ref to the
> > > creator's cred, then at both setns and write we could check the actor's
> > > credentials, right? There are probably issues with that specific idea,
> > > but that's why it would be good to see what else you've considered.
> >
> > Checking at write time alone doesn't work: once a task is inside the
> > namespace its cred says nothing about what it could do outside, so a
> > joiner and the creator look the same.
> >
> > It does work if setns() refuses to join a namespace that maps, or can
> > still map, the parent's uid 0 unless the joiner has CAP_SETFCAP over the
> > parent. Then everybody in a namespace has the same reach, and it can be
>
> Yeah, that's what I was thinking. Or even stricter: ensure that to join
> any user namespace, a process must have a superset of the namespace
> creator's capabilities.

I think both are fine and I like this proposal.

>
> > a level stored on the namespace at create time instead of a cred ref,
> > which would pin keyrings and the rest for the life of the namespace.

Yeah, that's what I was worrying as well.

Fwiw, this brings me to another general idea of mine: I want to be able
to pin a "creds" light variant that doesn't pin all the unnecessary cred
cruft like keyrings that you really don't need in a lot of cases. Like a
core cred reference that does namespaces uids/gids, caps and ucount but
drops all the rest.

> > The checks would be setns(), the map write (opener and writer are in the
> > parent, so a plain capable check), setxattr of security.capability, and
> > ptrace.
> >
> > The difference in behaviour is that the -EPERM moves to setns(): a root
> > task without CAP_SETFCAP couldn't enter a root-owned container that maps
> > host uid 0 at all, where with this series it can enter and is refused
> > only for the map, fscaps and ptrace. I can prototype it if you prefer
> > that.
>
> Sorry let me think about it (or let us talk about it) a bit more.

I think that this is an acceptable restriction. Mapping uid 0 to 0 and
dropping caps is borderline useless.