mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: Serge Hallyn <serge@hallyn.com>, Paul Moore <paul@paul-moore.com>,
	 Christian Brauner <brauner@kernel.org>
Cc: James Morris <jmorris@namei.org>,
	David Howells <dhowells@redhat.com>,
	 Jarkko Sakkinen <jarkko@kernel.org>,
	"Andrew G. Morgan" <morgan@kernel.org>,
	 Serge Hallyn <sergeh@kernel.org>,
	linux-security-module@vger.kernel.org,
	 linux-kernel@vger.kernel.org, keyrings@vger.kernel.org,
	 linux-fsdevel@vger.kernel.org,
	Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH v2 2/5] userns: don't let setns() lend CAP_SETFCAP
Date: Wed, 14 Oct 2026 20:47:47 +0000	[thread overview]
Message-ID: <20261014-b4-setfcap-userns-v2-2-fac4d19281d7@toxicpanda.com> (raw)
In-Reply-To: <20261014-b4-setfcap-userns-v2-0-fac4d19281d7@toxicpanda.com>

Mapping uid 0 of the parent into a user namespace requires CAP_SETFCAP,
because a task in such a namespace can write file capabilities that are
honoured in the parent.  A task that is already in the namespace has a
full capability set there and can't be asked any more, so
verify_root_map() goes by what the creator had, now ns->setfcap_level.

But setns() lets other tasks in, and they get the full set as well:

  task A: uid 0, full caps          task B: uid 0, no CAP_SETFCAP
  unshare(CLONE_NEWUSER)
                                    setns(A's user ns)
                                      allowed, euid == ns->owner
                                    write "0 0 1" to /proc/self/uid_map
                                      ns->setfcap_level is A's -> allowed

or, if A's namespace maps uid 0 already, B sets security.capability on a
file.  Either way B ends up with file capabilities that are honoured in
the initial namespace, which it could not have written there, nor in a
namespace it created itself.

Refuse setns() into a user namespace unless the joiner's CAP_SETFCAP
reaches at least as far up as the namespace's setfcap_level.  Then every
task in a namespace is entitled to what its setfcap_level says, and the
checks on the way to file capabilities can go by the namespace.  This
has to apply to every user namespace, also to those that don't map the
parent's uid 0: through an idmapped mount, a root user that only exists
in the namespace can be stored as the parent's.

The change in behaviour is that a task without CAP_SETFCAP gets -EPERM
when it tries to setns() into a user namespace created by a task that
had it, such as a root-created container.  Tasks with CAP_SETFCAP, and
unprivileged users joining their own namespaces, are not affected.

Fixes: db2e718a4798 ("capabilities: require CAP_SETFCAP to map uid 0")
Assisted-by: LLM
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel/user_namespace.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index a5a94367600d..330085a7d7d4 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -1390,6 +1390,13 @@ static int userns_install(struct nsset *nsset, struct ns_common *ns)
 	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
+	/* Everybody in the namespace gets CAP_SETFCAP that reaches as far up
+	 * as its setfcap_level, so only let in tasks whose own reaches as far.
+	 */
+	if (cap_setfcap_level(current_cred(), user_ns->parent) >
+	    user_ns->setfcap_level)
+		return -EPERM;
+
 	cred = nsset_cred(nsset);
 	if (!cred)
 		return -EINVAL;

-- 
2.55.0


  parent reply	other threads:[~2026-10-14 20:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-14 20:47 [PATCH v2 0/5] capabilities: close the ways around the CAP_SETFCAP rule for uid 0 Josef Bacik
2026-10-14 20:47 ` [PATCH v2 1/5] userns: record how far up CAP_SETFCAP reaches Josef Bacik
2026-10-14 20:55   ` Bradley Morgan
2026-10-14 20:47 ` Josef Bacik [this message]
2026-10-14 20:54   ` [PATCH v2 2/5] userns: don't let setns() lend CAP_SETFCAP Bradley Morgan
2026-10-14 20:47 ` [PATCH v2 3/5] userns: check the opener and the writer before mapping uid 0 Josef Bacik
2026-10-14 20:57   ` Bradley Morgan
2026-10-14 20:47 ` [PATCH v2 4/5] capabilities: limit fscaps to where CAP_SETFCAP reaches Josef Bacik
2026-10-14 20:47 ` [PATCH v2 5/5] capabilities: don't let ptrace borrow CAP_SETFCAP Josef Bacik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261014-b4-setfcap-userns-v2-2-fac4d19281d7@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=brauner@kernel.org \
    --cc=dhowells@redhat.com \
    --cc=jarkko@kernel.org \
    --cc=jmorris@namei.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=morgan@kernel.org \
    --cc=paul@paul-moore.com \
    --cc=serge@hallyn.com \
    --cc=sergeh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®