From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.218.69 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793275869; b=5B5TwuCr28ep8n+HxXWi3a960kJD5f3Ok87dBtYvhU6Y8VVlOVl2xPc4oxbkB2ZUek3e 1PIvZ/CHgKXW6omug/J+8mMUHvEmo/hvV12AhXVlxS77ZQoNMl5NdkxtXbrqJlkQgaJQ/ ue/zBnYgZAFEYmd4npd8o9CeL6htWZ6wlHqvLJOnKnT/FGYTSVPPAwXDgJWQ5VuN8+wQH JkqHWqKxTZCl8lfwLLq4af3WC9uy+NBMPn2HjqPL+cT2I1JoE/5s431KUL07MRdRZYbbW ESQT98IKPmHE1XExV6p3cnBORMWlhvWB1bgf7b5ePSty8KjQSVky+/mbxIERJ9YOd+A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793275869; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Received:Date:In-Reply-To: Mime-Version:References:Message-ID:Subject:From:To:Cc:Content-Type: Content-Transfer-Encoding; bh=8Jb0QjN+ngY6etMxQOZMOoIlhB+546T+PND1NORcPzA=; b=HZeJWbAulcqg15eMHLz9iSIcuVOWJNxPIjOoKSgjxRhLmmZLlfNkhbBjRy+DD5rdjSzG 6w1F7WY9Gi9CIjc5SAvTwfCHeaCq4srZ6XNeOaaKFuWzXZptGd4799cid2ioTkJvGaHhF cmxGuUAdRCXAyZctEtId3DzkPYcIkX9If6UZvZQ9mQUzETJVHIIsukF5+40Lg1ob8wmMv U80zFiRNZlrCTvMz5XEeSbFyIBAu6vTUnWGVsYbImU3/vucx/P7hWiWTJCM100wSpapRZ wvIDdgfnIXo1G2CZGgclQEe93R2rrDUEvpHGLNvfymT/GvBwe7Zf44ZyqyR5itF/lpA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=google.com; spf=pass smtp.mailfrom=flex--halg.bounces.google.com; dkim=pass header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20260707 header.b="Jlnl/QUT"; arc=none smtp.remote-ip=209.85.218.69 Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8D57606A324 for ; Thu, 29 Oct 2026 12:11:08 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org A8D57606A324 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--halg.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20260707 header.b=Jlnl/QUT Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-c293e604f0eso225202266b.3 for ; Thu, 29 Oct 2026 05:11:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20260707; t=1793275867; x=1793880667; darn=vger.kernel.org; h=content-transfer-encoding:content-type:cc:to:from:subject :message-id:references:mime-version:in-reply-to:date:from:to:cc :subject:date:message-id:reply-to:content-type; bh=8Jb0QjN+ngY6etMxQOZMOoIlhB+546T+PND1NORcPzA=; b=Jlnl/QUTtPccNXi+ZNNtbAqFpxXTju7rbaudqoEAepuOGdczXzyFQiuTlvKV9TRJFk Fp6YrBzWkmYN3bqS/G8vDFtnVhiAlhRXvYxV7V3Wg4R2R56JN4EzGTkxQscvA2DHXocH xqv3pRmejhrrxLL6D1jiPl6quIY++yph2+5UyvcgdWP33jRH+zU9UlGvQGFJZw9M4vFC ah2J/703hoBaTXZRxbDhVBoL5SfyHkCEuaYbCEzb9LGTWdPAX6cLywrWb24VDZrVPpED i84/UyEbcaXba0ha2kGdCV6YnJ0ZZq2iJ/jvKqL+jER6wtiVUy1Jw/OVcWsxlFH9UdV/ cpoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793275867; x=1793880667; h=content-transfer-encoding:content-type:cc:to:from:subject :message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=8Jb0QjN+ngY6etMxQOZMOoIlhB+546T+PND1NORcPzA=; b=M1j61ltzK9xqQIZoTILM0AaZZWMEyGE8wEziWvLY2GIHSU4fFwbJuXA13wYMvhVOlx xmx7X+nonv7suEwD/7ZQ4deWFCqASuqoH3rbnIgN67MPiJ0C8Jn5BmLI0mOla/p3CTFZ oSgTLU4+6OYJR8n0cbbwdKYxRPVtQCoPiwwo3SfbY7oUoabGh7JxTowm/mdSsNyup4lh 8Sh87VBZFX8EnkFDSwF9wXq2PPxBHAUsmF/qcu4ko7Jmgj9G42KGkn2THQHodFu2PdEj 5bjcFQ25pllwCIEK+ctww7pX4rpR8R/80j+Nbe6K6RSwME0ki8c4NWFUprD8ehsOccRm aHFA== X-Forwarded-Encrypted: i=1; AKwUvBxBJT3+p3jjZcgCFDrvd36PWJuCNimyWuTgnAzUMQtYHcO41RgO895qIRI2CN9x31DqHf/+TB1BzUO6ikL9P/o=@vger.kernel.org X-Gm-Message-State: AFq9FYKprMSi1lTgH1WJ5bxfCDPdVzA4stjAfJ6HQczhGc9BqOWpTP5V Baq+twn+JtYA3vpwqxNmywfeU6sYOkFJ4CYvZi+xMcld4mj/BBiIDI80L1DDqIFcln321c3GxA= = X-Received: from ejoy1.prod.google.com ([2002:a17:906:4481:b0:c49:cd3a:2b6e]) (user=halg job=prod-delivery.src-stubby-dispatcher) by 2002:a17:907:ecc5:b0:c49:d058:6901 with SMTP id a640c23a62f3a-c49d05873a3mr206311266b.38.1793275866775; Thu, 29 Oct 2026 05:11:06 -0700 (PDT) Date: Thu, 29 Oct 2026 12:11:06 +0000 In-Reply-To: X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list Mime-Version: 1.0 References: <20261028221705.3915340-1-halg@google.com> Message-ID: Subject: Re: [PATCH 0/8] userns: per-namespace capability bounding set and opt-in netns loopback From: "Hallgrimur H. Gunnarsson" To: Andy Lutomirski Cc: Christian Brauner , Alexander Viro , Paul Moore , Serge Hallyn , Kees Cook , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Jan Kara , James Morris , Simon Horman , Jonathan Corbet , Shuah Khan , Randy Dunlap , Jann Horn , "=?utf-8?Q?G=C3=BCnther?= Noack" , KP Singh , Jonathan Calmels , Casey Schaufler , linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, linux-api@vger.kernel.org, containers@lists.linux.dev, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable On Wed, Oct 28, 2026 at 03:56:11PM -0700, Andy Lutomirski wrote: > On Wed, Oct 28, 2026 at 3:18=E2=80=AFPM Hallgrimur H. Gunnarsson > wrote: > > > > When an unprivileged process creates a new user namespace, it is grante= d > > a full set of capabilities (CAP_FULL_SET) scoped to that namespace. > > While these capabilities are isolated to the namespace, they allow > > unprivileged local users to reach deep kernel subsystems (most notably > > networking configuration and raw sockets via CAP_NET_ADMIN and > > CAP_NET_RAW) that historically assumed a trusted caller and have > > accounted for a large share of local privilege escalation > > vulnerabilities. > > > > Many workloads and sandboxes use unprivileged user namespaces strictly > > for basic UID/GID, mount, PID, or network isolation and never need > > high-risk capabilities like CAP_NET_ADMIN or CAP_NET_RAW. Likewise, > > system administrators often want a host-wide policy ceiling restricting > > which capabilities unprivileged user namespaces may acquire, without > > disabling unprivileged user namespaces altogether. > > > > Prior work by Jonathan Calmels [1] proposed addressing this via a sixth > > per-thread capability set (cap_userns) alongside a global sysctl mask. > > During that discussion [1, 2], feedback (e.g. from Casey Schaufler) > > suggested that rather than adding another per-thread capability set and > > prctl() interface, capability restrictions could be integrated directly > > into struct user_namespace and configured via clone3(). At the same > > time, as noted in [1], a clone3() flag alone is not sufficient for > > administrators who need to enforce a host-wide ceiling on unprivileged > > user namespaces without modifying every userspace callsite. > > > > This series combines both pieces of feedback: it embeds a capability > > bounding set (cap_bset) directly into struct user_namespace, reusing > > the existing task cap_bset, cap_permitted, and cap_effective sets on > > namespace entry, and provides both a system-wide sysctl ceiling for > > unprivileged user namespaces and a CLONE_NEWUSER_BSET flag for > > voluntary per-namespace restriction via clone3(). >=20 > Why should the task's cap masks affect this? *Maybe* cap_bset makes > sense, but I'm struggling a bit to see why cap_permitted and > cap_effective should matter. Sorry, the phrasing here may have been misleading. Just to clarify: none of the creating task's capability sets (cap_bset, cap_permitted or cap_effective) are used to restrict the new user namespace. When I wrote "reusing the existing task cap_bset, cap_permitted and cap_effective sets on namespace entry", I was contrasting this with the prior series from 2024 [1], which proposed adding a 6th per-thread capability set to struct cred. In this series, when a task creates or enters a user namespace, we simply initialize its new cred->cap_{bset,permitted,effective} in that namespace to user_ns->cap_bset instead of CAP_FULL_SET. > Also, I think that Docker in non-userns mode restricts cap_bset, and > the purpose of that restriction is rather at odds with interpreting it > as a restriction on newly created user namespaces for purposes of > vulnerability mitigation. When computing the new user namespace's user_ns->cap_bset in create_user_ns(): 1. The creating task's cred->cap_bset and cred->cap_permitted are not consulted at all. The base ceiling is inherited from parent_ns->cap_bset (which is CAP_FULL_SET in init_user_ns), not from the task's cred->cap_bset. So a non-userns Docker container that drops bits from its task cap_bset does not restrict newly created user namespaces. 2. The creating task's cred->cap_effective never restricts the new user namespace, but it is used as an additive exception to the unprivileged sysctl ceiling. The rationale is that if an admin restricts e.g. CAP_NET_ADMIN in the unprivileged sysctl, an unprivileged daemon that already holds effective CAP_NET_ADMIN in the parent namespace is allowed to keep it when creating a new user namespace. There is no added attack surface if the user already had the capability in the parent ns. > > In addition, because restricting CAP_NET_ADMIN at user namespace > > creation time prevents userspace from bringing up the loopback > > interface in new network namespaces, the series first introduces > > an opt-in flag to automatically enable loopback on network namespace > > creation: > > > > 1. Opt-in loopback activation on netns creation (Patch 1) > > > > New network namespaces start with the loopback interface (lo) DOWN by > > default, requiring CAP_NET_ADMIN over the owning user namespace to > > bring it up. To block external network access while preserving > > localhost networking, sandboxes commonly create an isolated network > > namespace with only the loopback interface enabled. > > >=20 > The whole unshare/clone flag situation is getting out of hand, IMO. > And this new thing makes logical sense but is really about reducing > exposure. >=20 > Perhaps we should instead have a small list associated with a userns > (extensible in the future) of things that the ns's admin (i.e. whoever > has CAP_SYS_ADMIN relative to the ns) may do. That list could > include: >=20 > - Create loopback with sensible defaults for ipv4 and/or ipv6 (i see > no obvious reason to separate them) > - Create tun/tap interfaces in that ns (and attach them, etc) >=20 > And add a very simple new API to do these things. Actually, the > tun/tap could just use the normal mechanism. >=20 > Thoughts? I'm not particularly attached to CLONE_NEWNET_LOOPBACK. I'd be happy with whatever mechanism allows bringing up loopback in a new netns without granting all of CAP_NET_ADMIN. The main reason I went for a creation-time flag is that it avoids needing a separate userspace API call after namespace creation and makes it simple to get working loopback for sandboxes that want to drop all capabilities in the new userns from the start, e.g. CLONE_NEWUSER_BSET with cap_bset =3D 0. That said, if maintainers prefer not to spend clone/unshare flags on this, I'm completely open to an alternative mechanism. Also worth noting that Patch 1 is orthogonal to the rest of the series. The capability bounding set changes in Patches 2-4 stand on their own and Patch 1 just makes restricting CAP_NET_ADMIN more practical for common sandboxing use cases that rely on localhost networking.