The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v4 0/5] Implement LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
@ 2026-08-09 15:45 Justin Suess
  2026-08-09 15:45 ` [PATCH v4 1/5] landlock: Check landlock_restrict_self(2)'s flags before privileges Justin Suess
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Justin Suess @ 2026-08-09 15:45 UTC (permalink / raw)
  To: gnoack3000, mic; +Cc: linux-kernel, linux-security-module, Justin Suess

Howdy

This series adds a new landlock_restrict_self(2) flag:
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS.

The flag sets the no_new_privs attribute of the calling thread only
once the enforcement of the ruleset succeeded: no_new_privs is set if
and only if the landlock_restrict_self(2) call succeeds.

Semantics:

A single call replaces the usual prctl(PR_SET_NO_NEW_PRIVS) +
landlock_restrict_self(2) pair.  Because no_new_privs is set by the
call itself, the no_new_privs/CAP_SYS_ADMIN precondition is fulfilled
by construction, so the flag is usable by unprivileged processes.  This
is safe for the same reason the prctl(2) pair is: the executed programs
can either gain privileges or be restricted, never both.

The two states cannot diverge.  A failed call (invalid ruleset FD,
E2BIG, ENOMEM, interrupted TSYNC, ...) leaves no_new_privs unchanged,
and a successful call never returns without no_new_privs set: the
attribute is set past the last point of failure, right before
commit_creds(), which cannot fail.

Combined with LANDLOCK_RESTRICT_SELF_TSYNC, no_new_privs is set on all
threads with the same guarantee: each sibling thread sets it in the
commit phase of the TSYNC protocol, after its all-or-nothing barrier,
so either every thread gets both the domain and no_new_privs, or none
does.  This also makes it possible to set no_new_privs process-wide in
one call, which prctl(2) cannot do.

The flag requires a ruleset: calls with a ruleset_fd of -1 are
rejected.  Such a call would be nothing more than a Landlock-flavored
prctl(PR_SET_NO_NEW_PRIVS), and rejecting it keeps the option of giving
it a meaning later.

Following Mickaël's feedback on v3 [1], a new preparatory patch first
moves the no_new_privs/CAP_SYS_ADMIN check after the flags check, in
the same order as seccomp(2).  Unprivileged callers passing unknown
flag bits now consistently get EINVAL instead of EPERM, whether or not
the new flag is involved; the selftests pin this error ordering.

The Landlock ABI version is bumped to 11.

Test coverage:

base_test checks that a successful call sets no_new_privs without a
prior prctl(2) nor CAP_SYS_ADMIN, that a failed call (invalid ruleset
FD or layer maximum) leaves it unchanged, that the flag requires a
ruleset FD, and the flags-before-privileges error ordering.
tsync_test checks, through variants of a common multi_threaded
fixture, that TSYNC sets no_new_privs on sibling threads along with
the domain, and that a TSYNC call failing on the layer maximum leaves
it unset on every thread.

Changes since v3:

- New preparatory patch: check the landlock_restrict_self(2) flags
  before the no_new_privs/CAP_SYS_ADMIN requirement, like seccomp(2),
  per Mickaël's feedback.  The EINVAL/EPERM visible change now stems
  from this patch instead of the new flag.
- Folded the minimal selftest changes (ABI version, last-flag, and
  checks-ordering updates) into the main patch to keep the series
  bisectable, following the commit tweaked by Mickaël in his next
  branch.
- Dropped the set_no_new_privs local variable; the flag is now checked
  directly at both use sites.
- Turned the multi_threaded_{success,no_new_privs,
  no_new_privs_max_layers} tests into variants of a common
  multi_threaded fixture.
- Reworded the documentation: removed the ambiguous "it"s in the
  tutorial paragraph on CAP_SYS_ADMIN, and used the suggested
  "call (or CAP_SYS_ADMIN use)" wording in both the compatibility
  section and the uapi kdoc.

Per-patch changelogs are below each patch.

[1] https://lore.kernel.org/linux-security-module/20260803223109.707353-1-utilityemal77@gmail.com/

Justin Suess (5):
  landlock: Check landlock_restrict_self(2)'s flags before privileges
  landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
  selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
  landlock: Document LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
  samples/landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS to sampler

 Documentation/userspace-api/landlock.rst      |  47 +++++++-
 include/uapi/linux/landlock.h                 |  13 +++
 samples/landlock/sandboxer.c                  |  16 ++-
 security/landlock/limits.h                    |   2 +-
 security/landlock/syscalls.c                  |  35 ++++--
 security/landlock/tsync.c                     |   8 +-
 security/landlock/tsync.h                     |   4 +-
 tools/testing/selftests/landlock/base_test.c  | 104 +++++++++++++++++-
 tools/testing/selftests/landlock/tsync_test.c |  96 ++++++++++++++--
 9 files changed, 283 insertions(+), 42 deletions(-)

-- 
2.55.0


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

end of thread, other threads:[~2026-08-09 21:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-09 15:45 [PATCH v4 0/5] Implement LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-08-09 15:45 ` [PATCH v4 1/5] landlock: Check landlock_restrict_self(2)'s flags before privileges Justin Suess
2026-08-09 15:45 ` [PATCH v4 3/5] selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-08-09 15:45 ` [PATCH v4 4/5] landlock: Document LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-08-09 15:45 ` [PATCH v4 5/5] samples/landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS to sampler Justin Suess
2026-08-09 15:53 ` [PATCH v4 0/5] Implement LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-08-09 21:24 ` [PATCH v4 2/5] landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox