From: Justin Suess <utilityemal77@gmail.com>
To: gnoack3000@gmail.com, mic@digikod.net
Cc: linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Justin Suess <utilityemal77@gmail.com>
Subject: [PATCH v2 0/3] Implement LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
Date: Fri, 17 Jul 2026 18:03:16 -0400 [thread overview]
Message-ID: <20260717220320.1030123-1-utilityemal77@gmail.com> (raw)
Howdy
This series adds a new landlock_restrict_self(2) flag:
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS.
This is a redesign of v1 [1], which added
LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC, a flag staging no_new_privs so that
it was only set at the next execve(2). Following Mickaël's feedback,
[2] the staging mechanism (credential bit and bprm_committing_creds hook)
is dropped entirely. The new flag instead sets the no_new_privs
attribute of the calling thread atomically with the enforcement of the
ruleset: 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 atomically set no_new_privs
process-wide, which prctl(2) cannot do.
Unlike the v1 flag, this flag requires a ruleset: calls with a
ruleset_fd of -1 are rejected. As a consequence of the fulfilled
precondition, an unprivileged caller passing unknown flag bits together
with this flag receives EINVAL instead of EPERM; the selftests pin this
error ordering as well.
The reason why -1 ruleset_fd is rejected is basically then we are
making a Landlock-flaved prctl(nnp) call that doesn't do anything
special. It seems better to be able to have the option to define
behavior later rather than have a useless feature stuck in the
syscall abi. So we reject the -1 ruleset_fd for now.
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 leaves it
unchanged, that the flag requires a ruleset FD, and the updated
EPERM/EINVAL ordering. tsync_test checks that TSYNC sets no_new_privs
on sibling threads along with the domain.
Changes since v1:
- Renamed LANDLOCK_RESTRICT_SELF_NNP_ON_EXEC to
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS, per Mickaël's feedback.
- Dropped the staged "on exec" design: removed the credential bit and
the bprm_committing_creds hook; no_new_privs is now set atomically
with the ruleset enforcement.
- The flag now fulfills the no_new_privs/CAP_SYS_ADMIN precondition,
a significant departure from the v1.
- The flag now requires a ruleset (no ruleset_fd = -1). Otherwise such
a call would just == a vanilla prctl no-new-privs call. This is left
in case we want to repurpose it later rather than defining useless
redundant behavior.
[1] https://lore.kernel.org/linux-security-module/20260708133928.852999-1-utilityemal77@gmail.com/
[2] https://lore.kernel.org/linux-security-module/20260709.Eaphooyoh6sh@digikod.net/
Justin Suess (3):
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
Documentation/userspace-api/landlock.rst | 14 +++-
include/uapi/linux/landlock.h | 13 ++++
security/landlock/limits.h | 2 +-
security/landlock/syscalls.c | 28 ++++++--
security/landlock/tsync.c | 8 ++-
security/landlock/tsync.h | 4 +-
tools/testing/selftests/landlock/base_test.c | 65 +++++++++++++++++--
tools/testing/selftests/landlock/tsync_test.c | 33 ++++++++++
8 files changed, 150 insertions(+), 17 deletions(-)
base-commit: 55f82176ef8dde632ea3eb94a6224950ed809d7c
--
2.54.0
next reply other threads:[~2026-07-17 22:03 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 22:03 Justin Suess [this message]
2026-07-17 22:03 ` [PATCH v2 1/3] landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-07-31 21:29 ` Mickaël Salaün
2026-07-31 22:43 ` Justin Suess
2026-07-17 22:03 ` [PATCH v2 2/3] selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-07-31 21:29 ` Mickaël Salaün
2026-07-17 22:03 ` [PATCH v2 3/3] landlock: Document LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Justin Suess
2026-07-31 21:34 ` Mickaël Salaün
2026-07-31 21:28 ` [PATCH v2 0/3] Implement LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS Mickaël Salaün
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=20260717220320.1030123-1-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=gnoack3000@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mic@digikod.net \
/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 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.