All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] userns: per-namespace capability bounding set and opt-in netns loopback
@ 2026-10-28 22:16 Hallgrimur H. Gunnarsson
  2026-10-28 22:16 ` [PATCH 1/8] net: introduce CLONE_NEWNET_LOOPBACK to auto-enable loopback Hallgrimur H. Gunnarsson
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Hallgrimur H. Gunnarsson @ 2026-10-28 22:16 UTC (permalink / raw)
  To: Christian Brauner, Alexander Viro, Paul Moore, Serge Hallyn,
	Kees Cook, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni
  Cc: Jan Kara, James Morris, Simon Horman, Jonathan Corbet, Shuah Khan,
	Randy Dunlap, Jann Horn, Günther Noack, KP Singh,
	Jonathan Calmels, Casey Schaufler, linux-fsdevel,
	linux-security-module, linux-api, containers, netdev, linux-doc,
	linux-kselftest, linux-kernel, Hallgrimur H. Gunnarsson

When an unprivileged process creates a new user namespace, it is granted
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().

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.

  However, requiring a sandbox to hold CAP_NET_ADMIN in a new user
  namespace solely to bring loopback up conflicts with reducing the
  CAP_NET_ADMIN attack surface. Today, an unprivileged sandbox must
  start with CAP_NET_ADMIN to bring loopback up, drop it, and then
  block CAP_NET_ADMIN from being regained in nested user namespaces
  (e.g. via seccomp or max_user_namespaces limits). Conversely, when
  CAP_NET_ADMIN is restricted at user namespace creation time (via the
  sysctl ceiling or CLONE_NEWUSER_BSET introduced in Patches 2-3, or
  via LSMs such as Landlock), tasks inside the new namespace never
  acquire CAP_NET_ADMIN and cannot bring loopback up from userspace,
  breaking localhost networking for unprivileged sandboxes.

  Introduce the CLONE_NEWNET_LOOPBACK flag for clone3() and the
  corresponding UNSHARE_NEWNET_LOOPBACK flag for unshare(), which imply
  CLONE_NEWNET and automatically bring the loopback device up in
  copy_net_ns() before returning the new network namespace. Making this
  an explicit opt-in preserves default network namespace semantics
  while allowing unprivileged sandboxes to create an isolated network
  namespace with functional localhost networking without ever holding
  CAP_NET_ADMIN.

2. Per-user-namespace capability bounding set & sysctl ceiling (Patch 2)

  Add cap_bset to struct user_namespace (initialized to CAP_FULL_SET in
  init_user_ns) and introduce a system-wide sysctl ceiling for
  unprivileged users at:
    /proc/sys/kernel/unprivileged_userns_caps_allowed
  (defaulting to CAP_FULL_SET).

  When a new user namespace is created:
  - Privileged creators (holding CAP_SYS_ADMIN in the parent user
    namespace) inherit cap_bset from the parent user namespace.
  - Unprivileged creators (lacking CAP_SYS_ADMIN in the parent user
    namespace) have the child namespace's bounding set constrained by
    the sysctl ceiling combined with any effective capabilities the
    creator already holds in the parent namespace:
        child_bset = parent_bset & (sysctl_ceiling | creator_effective)
    Allowing the creator to retain capabilities it already holds in the
    parent namespace ensures that a process granted a specific
    capability (e.g. CAP_NET_ADMIN) does not lose it when creating a
    nested user namespace.

  When a task enters a user namespace via clone()/unshare() or
  setns(), its cap_bset, cap_permitted, and cap_effective sets are
  clamped to user_ns->cap_bset. In addition, cap_capable_helper() is
  updated so that implicit capabilities granted to the parent-namespace
  owner of a user namespace are likewise bounded by the owned
  namespace's cap_bset.

3. Per-namespace restriction via clone3() (Patch 3)

  Introduce CLONE_NEWUSER_BSET and add cap_bset to struct clone_args.
  When specified alongside CLONE_NEWUSER, the new user namespace's
  bounding set is further intersected with the requested cap_bset mask,
  allowing container runtimes and sandboxes to drop unneeded capabilities
  from a user namespace at creation time even when permitted by the
  global sysctl.

4. Introspection via NS_USER_GET_INFO (Patch 4)

  While tasks inside a user namespace see their initial ceiling in
  /proc/<pid>/status (CapBnd), threads may subsequently drop
  individual capabilities from their per-thread bounding set. Add
  an extensible NS_USER_GET_INFO ioctl on userns file descriptors
  to allow userspace to directly query a user namespace's cap_bset.

5. Selftests (Patches 5-8)

  Add kselftest suites covering CLONE_NEWNET_LOOPBACK, the sysctl
  ceiling, creator capability retention, nested monotonicity,
  parent-owner bounding, CLONE_NEWUSER_BSET and NS_USER_GET_INFO.

[1] https://lore.kernel.org/all/20240609104355.442002-1-jcalmels@3xx0.net/
[2] https://lwn.net/Articles/978846/

Note on tree routing:

While Patch 1 (CLONE_NEWNET_LOOPBACK) touches net/core/net_namespace.c,
most of its changes add clone3()/unshare() flag plumbing in
include/uapi/linux/sched.h, kernel/fork.c, and kernel/nsproxy.c, which
Patch 3 (CLONE_NEWUSER_BSET) builds directly on top of. To avoid
merge conflicts in kernel/fork.c and include/uapi/linux/sched.h, it
may be simplest to route the entire series through a single tree, e.g.
a namespace branch in vfs.git with Acked-by from the netdev and
capabilities/credentials maintainers, or whichever tree the maintainers
prefer.

Hallgrimur H. Gunnarsson (8):
  net: introduce CLONE_NEWNET_LOOPBACK to auto-enable loopback
  userns: introduce capability bounding set for user namespaces
  userns: allow restricting capability bounding set via clone3()
  nsfs: add NS_USER_GET_INFO ioctl to inspect user namespace
    capabilities
  selftests/net: add test suite for CLONE_NEWNET_LOOPBACK
  selftests/capabilities: tests for user namespace capability bounding
    set
  selftests/capabilities: add clone3() tests for CLONE_NEWUSER_BSET
  selftests/nsfs: add tests for NS_USER_GET_INFO ioctl

 Documentation/admin-guide/sysctl/kernel.rst   |  37 ++
 fs/nsfs.c                                     |  29 +
 include/linux/cred.h                          |   3 +-
 include/linux/sched/task.h                    |   1 +
 include/linux/user_namespace.h                |  20 +-
 include/uapi/linux/nsfs.h                     |  17 +
 include/uapi/linux/sched.h                    |   9 +
 kernel/cred.c                                 |  10 +-
 kernel/fork.c                                 |  38 +-
 kernel/nsproxy.c                              |   9 +
 kernel/user.c                                 |   1 +
 kernel/user_namespace.c                       | 100 +++-
 net/core/net_namespace.c                      |  11 +
 security/commoncap.c                          |   8 +-
 .../testing/selftests/capabilities/.gitignore |   1 +
 tools/testing/selftests/capabilities/Makefile |   2 +-
 .../capabilities/userns_bounding_set_test.c   | 566 ++++++++++++++++++
 .../selftests/clone3/clone3_selftests.h       |   1 +
 .../selftests/filesystems/nsfs/.gitignore     |   1 +
 .../selftests/filesystems/nsfs/Makefile       |   4 +-
 .../selftests/filesystems/nsfs/userns.c       | 120 ++++
 tools/testing/selftests/net/.gitignore        |   1 +
 tools/testing/selftests/net/Makefile          |   1 +
 tools/testing/selftests/net/loopback_netns.c  | 103 ++++
 24 files changed, 1069 insertions(+), 24 deletions(-)
 create mode 100644 tools/testing/selftests/capabilities/userns_bounding_set_test.c
 create mode 100644 tools/testing/selftests/filesystems/nsfs/userns.c
 create mode 100644 tools/testing/selftests/net/loopback_netns.c


base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
-- 
2.56.0.313.g2479322e68-goog


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-10-29 22:18 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28 22:16 [PATCH 0/8] userns: per-namespace capability bounding set and opt-in netns loopback Hallgrimur H. Gunnarsson
2026-10-28 22:16 ` [PATCH 1/8] net: introduce CLONE_NEWNET_LOOPBACK to auto-enable loopback Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:16 ` [PATCH 2/8] userns: introduce capability bounding set for user namespaces Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 3/8] userns: allow restricting capability bounding set via clone3() Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 4/8] nsfs: add NS_USER_GET_INFO ioctl to inspect user namespace capabilities Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 5/8] selftests/net: add test suite for CLONE_NEWNET_LOOPBACK Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 6/8] selftests/capabilities: tests for user namespace capability bounding set Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 7/8] selftests/capabilities: add clone3() tests for CLONE_NEWUSER_BSET Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:17 ` [PATCH 8/8] selftests/nsfs: add tests for NS_USER_GET_INFO ioctl Hallgrimur H. Gunnarsson
2026-10-29 22:18   ` sashiko-bot
2026-10-28 22:56 ` [PATCH 0/8] userns: per-namespace capability bounding set and opt-in netns loopback Andy Lutomirski
2026-10-29 10:44   ` Alexey Gladkov
2026-10-29 12:11   ` Hallgrimur H. Gunnarsson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.