Commit Graph

180 Commits

Author SHA1 Message Date
Mickaël Salaün
c8dcb17205
selftests/landlock: Test network denial context
Network denial events now report the port from their one authoritative
validated address through one signed field.  Verify this value directly
without inferring a source or destination role.

Exercise a nonzero IPv4 TCP bind, an explicit-zero IPv4 UDP bind, a
synthetic-zero IPv6 UDP autobind, and a family-only AF_UNSPEC UDP send.
Require exactly one event with the exact policy blocker for each shape.
The value -1 distinguishes a family-only address with no validated port
from the two valid port-zero cases.

Test coverage for security/landlock is 91.6% of 2625 lines according to
LLVM 22.

Cc: Günther Noack <gnoack@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: https://patch.msgid.link/20260918185036.608651-9-mic@digikod.net
[mic: Add test coverage]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-20 14:13:31 +02:00
Mickaël Salaün
c6dea91d84
selftests/landlock: Test filesystem denial blockers
Filesystem denial traces identify the policy change needed to allow a
request, so require exact blocker values rather than merely nonempty
output. Pin a READ_DIR denial to exactly one event with
blockers=read_dir. Pin a REFER-only mount denial to EPERM and exactly
one event with blockers=change_topology.

The mount child retains CAP_SYS_ADMIN so Landlock is the only expected
source of EPERM.  This prevents a later capability failure from masking
a Landlock regression; the trace-collecting parent remains unsandboxed.

Cc: Günther Noack <gnoack@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: https://patch.msgid.link/20260918185036.608651-8-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-20 11:08:05 +02:00
Mickaël Salaün
98b04ab00f
landlock: Fix network denial trace context
Network denial events report source and destination ports reconstructed
from audit data. Their zero values are ambiguous, and neither identifies
the complete endpoint that Landlock checked.

Carry the checked sockaddr and its signed length in a private trace-only
context. For an enabled event, validate the length and copy only the
initialized prefix into zeroed local storage. This prevents a typed BPF
program from reading uninitialized bytes while exposing the socket
family, socket, address, and length.

Replace the source and destination trace-record fields with one signed
port derived from the checked address. A value of -1 means that no port
was checked, zero is a valid port, and positive values use host
endianness. Bind blockers select the bind address; connect and send
blockers select the destination.

Cc: Günther Noack <gnoack@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Fixes: 01ce260f5c ("landlock: Add landlock_deny_access_fs and landlock_deny_access_net")
Link: https://patch.msgid.link/20260918185036.608651-5-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-20 11:08:02 +02:00
Mickaël Salaün
1a985d3890
landlock: Fix rule tracepoint context
Name each event after the identity it reports. Add-rule events describe
UAPI rule insertion, so rename them after LANDLOCK_RULE_PATH_BENEATH and
LANDLOCK_RULE_NET_PORT. Check-rule events describe matches in internal
rule trees, so rename them after LANDLOCK_KEY_INODE and
LANDLOCK_KEY_NET_PORT. This remains accurate if multiple UAPI rule types
share one lookup and stored rule. Keep denial event names based on
filesystem and network families because they describe final access
decisions.

Use u64 for growable access masks passed by value to add-rule and
check-rule typed BTF callbacks. CO-RE can relocate pointer-reached
fields, but it cannot widen a scalar callback slot declared by a BPF
program. Keep native access_mask_t for internal state and trace records.

For add-rule callbacks, report the normalized per-call contribution
passed to landlock_insert_rule() and expose the complete validated flags
value. Put the ruleset and flags first as a common invocation prefix.
This distinguishes duplicate and effective-zero additions without
recovering arguments from saved syscall registers.

Cc: Günther Noack <gnoack@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Fixes: 63747c9477 ("landlock: Add landlock_add_rule_fs and landlock_add_rule_net tracepoints")
Fixes: 3f1f106e4c ("landlock: Add tracepoints for rule checking")
Link: https://patch.msgid.link/20260918185036.608651-4-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-20 11:08:02 +02:00
Mickaël Salaün
d41d0021a6
landlock: Test trace path output boundaries
Use focused KUnit tests to exercise the renderer's internal boundary and
composition contracts with synthetic scratch states, including both
sibling-helper evaluation orders.  Check the exact output and
reservation boundaries, including a four-byte octal escape accepted at
exact capacity and rejected one byte short.  Also verify an unchanged
cursor on failure, that bracketed process names and embedded NUL bytes
remain data, and that input ellipsis bytes are escaped rather than
mistaken for the raw truncation marker.

The composition test requires generic trace output helpers.  Enable
CONFIG_FTRACE and CONFIG_SCHED_TRACER because the latter selects the
otherwise-hidden CONFIG_TRACING support required by
trace_print_flags_seq().

Use kselftests to exercise the complete tracefs path for both affected
filesystem events.  A valid path containing 2640 spaces exceeds the
scratch output budget.  Require its escaped prefix to end in the raw
UTF-8 ellipsis while access_rights and blockers remain intact.

This division keeps the exact safety contract compiler-independent while
proving that real tracepoints preserve their surrounding symbolic
fields.  The end-to-end assertions fail after a full fix revert with
both GCC and Clang, while the composition KUnit test fails if the
scratch reserve is removed.

Cc: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260907154401.124362-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-08 11:49:39 +02:00
Mickaël Salaün
e7557b9ef7
selftests/landlock: Test abstract socket trace name limits
The landlock_deny_scope_abstract_unix_socket event captures binary
socket names with __string_len(), whose dynamic field reserves an extra
byte for the NUL terminator.  The printer subtracts this byte before
escaping the content.

Exercise the minimum accepted address length, which has no name content,
and the maximum sockaddr_un length, which has 107 content bytes.  Check
the exact trace output at both boundaries.  The existing stream and
datagram variants share this event, so the boundary variants only need
the stream path.

Because these boundary names are fixed, run the fixture in a private
network namespace.  Abstract UNIX socket names are scoped by network
namespace, preventing concurrent bind() calls from colliding.

The lower-bound test confirms that the subtraction recovers zero instead
of underflowing.

Cc: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/CAL4aGcVcT0VWVFmGi_vLqxxZ9KdOHfGXYZtKjBdvoUyFjbu5=A@mail.gmail.com
Link: https://patch.msgid.link/20260907103503.109461-1-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-09-07 12:38:01 +02:00
Mickaël Salaün
ac6d193de5
selftests/landlock: Add landlock_enforce_domain trace tests
Add trace tests for the landlock_enforce_domain event in trace_test.c,
asserting field counts after the syscall returns rather than line
ordering across per-CPU buffers.  They cover single-threaded and TSYNC
enforcement (complete and process_wide set), a multi-threaded non-TSYNC
process (process_wide clear), the single-threaded non-leader edge case,
the flags-only path that creates no domain, and a thread-sync abort that
emits create_domain and free_domain but no enforce_domain.

landlock_enforce_domain is added to the fixture enable path and every
disable list so its zero-events assertions cannot be tripped by a stray
enforcement event.

Test coverage for security/landlock is 91.6% of 2571 lines according to
LLVM 22.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/20260811094338.288094-19-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-17 10:17:19 +02:00
Mickaël Salaün
aef2dd32dd
selftests/landlock: Add scope and ptrace tracepoint tests
Add trace tests for the landlock_deny_ptrace,
landlock_deny_scope_signal, and landlock_deny_scope_abstract_unix_socket
tracepoints, each placed alongside the functional tests for its
subsystem, mirroring the audit test layout.

Each tracepoint is exercised by a fixture with three variants that pin
both branches of the other-party domain field: denied against an
unsandboxed other party (other-party domain ID 0), denied against a
sandboxed other party (non-zero ID), and an allowed baseline that
records no event.  A second fixture per type exercises an alternate LSM
hook that reaches the same tracepoint with the same other-party domain
ID, since each denial type can be reached through more than one hook.

The datagram abstract-unix variant does not assert peer_pid, which is 0
for a datagram peer (no SO_PEERCRED); sun_path is the reliable peer
identifier.  The ptrace fixtures install a plain domain-creating ruleset
rather than a dedicated flag, since ptrace denial relies on domain
ancestry, not on a specific scoped flag.  The fixtures unshare the mount
namespace and remount / as MS_PRIVATE before mounting tracefs so the
helper instance is visible only to the test process.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/20260811094338.288094-18-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-17 10:17:18 +02:00
Mickaël Salaün
6e2df0117b
selftests/landlock: Add network tracepoint tests
Add network-specific trace tests, co-located with the existing audit
fixture so each subsystem's functional, audit, and trace tests live
together.

Parameterized fixtures verify the landlock_deny_access_net event: a bind
or connect denied outside the ruleset emits exactly one event with the
expected sport/dport, an allowed bind or connect emits none, and the
unsandboxed baseline emits none.  A separate fixture verifies the
landlock_check_rule_net event on an allowed bind, anchoring its domain,
access_request, port, and grants to exact values; only check_rule_fs had
a dedicated field test before.

Port fields are read in host endianness, matching the
landlock_net_port_attr.port UAPI convention, so the decimal comparisons
also catch byte-order regressions in the tracepoint plumbing.  IPv6
trace tests are intentionally elided: IPv6 hook dispatch shares the
current_check_access_socket() path with IPv4 (covered by the audit
tests), and the trace fields do not depend on address family.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/20260811094338.288094-17-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-17 10:17:18 +02:00
Mickaël Salaün
30478db56c
selftests/landlock: Add filesystem tracepoint tests
Add filesystem-specific trace tests in a dedicated file, following the
audit-test pattern of living alongside each subsystem's functional
tests.

trace_fs_test.c verifies that the add_rule_fs, check_rule_fs, and
deny_access_fs events fire with the correct fields on matching rules and
denied accesses, that check_rule_fs does not fire for unhandled access
types, and that no event fires without a sandbox.  A denial covered by a
quiet rule still emits a deny_access_fs event but with logged=0, the
same suppression verdict audit applies; because that verdict must not
depend on CONFIG_AUDIT, the test also runs under a tracepoints-only
build.

Add trace_layout1 fixture tests in fs_test.c that reuse the layout1
hierarchy to verify the per-layer grants field: field values, multi-rule
pathwalk short-circuit, request intersection, the optional truncate
right surfacing in the request and grants, and an empty grants set from
a rule that grants none of the requested rights.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/20260811094338.288094-16-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-17 10:17:17 +02:00
Mickaël Salaün
2651712a15
selftests/landlock: Add trace event test infrastructure and tests
Add tracefs test infrastructure in trace.h: helpers for mounting
tracefs, enabling/disabling events, reading the trace buffer, counting
regex matches, and extracting field values, plus per-event regex
patterns.  The patterns are anchored with ^ and $, verify every
TP_printk field, and use no unescaped dot characters; TRACE_PREFIX
matches the ftrace line format with either the expected task name
(truncated to TASK_COMM_LEN - 1) or "<...>" for an evicted comm cache
entry.

Add trace_test.c with the trace fixture (setup enables all available
events with a PID filter, teardown disables and clears) and the
lifecycle, API, denial-field, and log-flag tests.  Extend the existing
true helper to open its working directory before exiting, triggering a
read_dir denial inside a sandbox, so the exec-based tests can verify
same_exec and the logged decision across an exec.  Move regex_escape()
from audit.h to common.h for shared use by the audit and trace tests.

Enable CONFIG_ENABLE_DEFAULT_TRACERS alongside CONFIG_FTRACE in the
selftest config: CONFIG_FTRACE alone only enables the tracer menu
without activating any tracer, while CONFIG_ENABLE_DEFAULT_TRACERS
selects TRACING (and thus TRACEPOINTS and event tracing) without
depending on architecture-specific syscall tracepoints.  When
CONFIG_FTRACE is disabled it cannot be set, so TRACEPOINTS is correctly
disabled too.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/20260811094338.288094-15-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-17 10:17:17 +02:00
Justin Suess
71f98bc6e5
selftests/landlock: Test LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
Check that a successful landlock_restrict_self(2) call with
LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS sets no_new_privs without a prior
prctl(2) call nor CAP_SYS_ADMIN, that a failed call from both an
invalid ruleset and hitting the layer maximum leaves the attribute
unchanged, and that LANDLOCK_RESTRICT_SELF_TSYNC extends it to sibling
threads.  Also check that this flag requires a ruleset.

Turn the multi_threaded_success test into a multi_threaded fixture with
success, no_new_privs, and no_new_privs_max_layers variants to factor
out the threading code.

Finally, rename restrict_self_fd_logging_flags to
restrict_self_fd_flags, and restrict_self_logging_flags to
restrict_self_flags to indicate that non-logging flags are now tested.

Test coverage for security/landlock is 91.8% of 2373 lines according to
LLVM 22.

Signed-off-by: Justin Suess <utilityemal77@gmail.com>
Link: https://patch.msgid.link/20260809154544.1253100-4-utilityemal77@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:47 +02:00
Justin Suess
6887c03bf2
landlock: Add LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS
Add a landlock_restrict_self(2) flag to set the no_new_privs attribute
of the calling thread only after enforcement of the ruleset:
no_new_privs is set if and only if the call succeeds.  This removes the
need for a prior prctl(2) PR_SET_NO_NEW_PRIVS call and guarantees that
a failed enforcement leaves the attribute unchanged.

Because no_new_privs is set by the call itself, the no_new_privs /
CAP_SYS_ADMIN requirement of landlock_restrict_self(2) is fulfilled by
construction, and the related EPERM check is skipped.

Unlike LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF, this flag always
requires a valid ruleset: with a ruleset_fd of -1, such a call would be
nothing more than a Landlock-flavored prctl(2) PR_SET_NO_NEW_PRIVS, and
there is no valid use case for setting no_new_privs (possibly with
LANDLOCK_RESTRICT_SELF_TSYNC) without also enforcing Landlock
restrictions.  Rejecting these calls also keeps the option of giving
them a meaning later.

The attribute is only set past the last point of failure, just before
committing the new credentials.  When combined with
LANDLOCK_RESTRICT_SELF_TSYNC, no_new_privs is set on the sibling threads
as well, in their commit phase, with the same ordering.

Bump the Landlock ABI version to 11, and include the minimal related
test changes to keep the tests bisectable.

Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
Link: https://patch.msgid.link/20260809212459.2427878-1-utilityemal77@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:46 +02:00
Justin Suess
c2fe8b60b8
landlock: Check landlock_restrict_self(2)'s flags before privileges
landlock_restrict_self(2) currently checks the no_new_privs /
CAP_SYS_ADMIN requirement before validating the flags argument.  An
unprivileged caller without no_new_privs thus gets EPERM even when the
passed flags are invalid, hiding the EINVAL error.

Move the no_new_privs / CAP_SYS_ADMIN check just after the flags check
so that malformed calls consistently error out with EINVAL whatever the
caller's privileges, the same way seccomp(2) validates its flags before
checking no_new_privs.

Update the restrict_self_checks_ordering test accordingly.

Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
Link: https://patch.msgid.link/20260809154544.1253100-2-utilityemal77@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:46 +02:00
Günther Noack
17522b96dc
selftests/landlock: Test whiteout object behaviour in OverlayFS renames
Even though OverlayFS uses vfs_rename() with RENAME_WHITEOUT on its
backing directories, and even though RENAME_WHITEOUT requires
LANDLOCK_ACCESS_FS_MAKE_REG, a process that renames non-regular files in
an OverlayFS can do so without having the LANDLOCK_ACCESS_FS_MAKE_REG
right in that location.

This works, and is supposed to work, because the changes to the backing
directories are done by OverlayFS, not by the originator task that did
the original rename() on the OverlayFS mount.  Therefore, the changes
done to backing directories are not subject to the originator task's
credentials.

Test coverage for security/landlock is 91.8% of 2368 lines according to
LLVM 22.

Signed-off-by: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260813093157.1436894-6-gnoack@google.com
[mic: Add test coverage, reflow commit message]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:44 +02:00
Günther Noack
8c46c6acbe
selftests/landlock: Add audit test for whiteout object creation
Add audit_layout1.make_whiteout: This test looks similar to
audit_layout1.make_char, but creates a whiteout object through mknod().
Since whiteout object creation is now guarded with
LANDLOCK_ACCESS_FS_MAKE_REG rather than LANDLOCK_ACCESS_FS_MAKE_CHAR, it
also needs to log the matching denial to audit.

Signed-off-by: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260813093157.1436894-5-gnoack@google.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:44 +02:00
Günther Noack
ee890889b3
selftests/landlock: Add tests for whiteout object creation
Add tests to check that whiteout object creation is guarded by
LANDLOCK_ACCESS_FS_MAKE_REG, in the cases where these are created from
userspace:

* Conventional creation with mknod()
* Linking or renaming an existing whiteout object
* renameat2() with RENAME_WHITEOUT,
  which creates a new whiteout object in the source location
* renameat2() with RENAME_EXCHANGE,
  with one of the renamed objects being a whiteout object

Signed-off-by: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260813093157.1436894-4-gnoack@google.com
[mic: Update commit message as requested]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:43 +02:00
Günther Noack
173b1bd873
selftests/landlock: Use an actual chardev for MAKE_CHAR audit test
By passing a (0, 0) device number, the audit test for
LANDLOCK_ACCESS_FS_MAKE_CHAR was accidentally creating a whiteout object
rather than a char device.  In preparation to treating whiteout objects
differently, use an actual character device instead.

Signed-off-by: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260813093157.1436894-2-gnoack@google.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-15 09:14:40 +02:00
Wang Yan
525acde34d
selftests/landlock: Fix spelling error in fs_test comment
Fix typo "allowes" -> "allows" in Landlock filesystem test comment.

Signed-off-by: Wang Yan <wangyan01@kylinos.cn>
Reviewed-by: Günther Noack <gnoack@google.com>
Link: https://patch.msgid.link/20260702015823.368529-1-wangyan01@kylinos.cn
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-08-14 12:38:29 +02:00
Thomas Huth
5ab1dc6d11
selftests/landlock: Skip scoped_signal subtest with MSG_OOB if not available
MSG_OOB might be disabled in the kernel for unix sockets (by not
selecting CONFIG_AF_UNIX_OOB), and in this case the related tests
of the scoped_signal_test are currently failing.  Add a runtime
probe using socketpair() to detect MSG_OOB support and skip the
test gracefully if it is unavailable.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Link: https://patch.msgid.link/20260710081642.405916-1-thuth@redhat.com
Cc: stable@vger.kernel.org
Fixes: f34e9ce5f4 ("selftests/landlock: Test signal created by out-of-bound message")
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-07-10 12:59:11 +02:00
Thomas Huth
d793186aa3
selftests/landlock: Fix screwed up pointers in the scoped_signal_test
The scoped_signal_test uses pthread_join(..., (void **)&ret)) in
a couple of places, i.e. the return value of the thread is stored
in the shape of a "void *" into the memory location of &ret.
Pointers are 64-bit on modern computers, but the ret variable is
declared as a simple "enum thread_return" which is only 32 bits.
So the pthread_join() will overflow the ret variable by 4 byte.

The problem is very visible on big endian systems like s390x
where the test is failing: The least significant byte that carries
the return code of the thread is not written into the ret variable
here, but somewhere else in the stack frame, so the comparison
for the right return code is failing here.

Fix it by getting rid of the enum and defining the THREAD_* constants
and "ret" variables as proper "void *" pointers. This way we can
also get rid of some ugly (void *) castings in a couple of spots.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Link: https://patch.msgid.link/20260709164340.339656-1-thuth@redhat.com
Cc: stable@vger.kernel.org
Fixes: c899496501 ("selftests/landlock: Test signal scoping for threads")
[mic: Add clang-format markups]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-07-10 12:59:11 +02:00
Matthieu Buffet
f4b30e0b1d
selftests/landlock: Add test for TCP fast open
Enforce that TCP Fast Open is controlled by
LANDLOCK_ACCESS_NET_CONNECT_TCP. Semantics of connect() and
sendmsg(MSG_FASTOPEN) should be identical from Landlock's perspective.
Also enforce error code consistency, since UDP sockets ignore the
MSG_FASTOPEN flag while Unix sockets reject it.

Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://patch.msgid.link/20260701214628.33319-2-matthieu@buffet.re
Cc: stable@vger.kernel.org
[mic: Fix formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-07-10 12:59:09 +02:00
Tingmao Wang
1c236e7fe7
selftests/landlock: Add tests for invalid use of quiet flag
Make sure that these calls return EINVAL.

Test coverage for security/landlock is 91.6% of 2347 lines according to
LLVM 22.

Assisted-by: GitHub-Copilot:claude-opus-4.8
Signed-off-by: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/9401d5c6468675863d944d6c26640d97db1a1f31.1781228815.git.m@maowtm.org
[mic: Add test coverage]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:25 +02:00
Tingmao Wang
1493675453
selftests/landlock: Add tests for quiet flag with scope
Enhance scoped_audit.connect_to_child and audit_flags.signal to test
interaction with various quiet flag settings.

Signed-off-by: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/032849ca97bd45b2e14f96192b61537ed9405a0d.1781228815.git.m@maowtm.org
[mic: Fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:24 +02:00
Tingmao Wang
624c96268b
selftests/landlock: Add tests for quiet flag with net rules
Tests that:
- Quiet flag works on network rules
- Quiet flag applied to unrelated ports has no effect
- Denied access not in quiet_access_net is still logged

This is not as thorough as the fs tests, but given the shared logic it
should be sufficient.  There is also no "optional" access for network
rules.

Signed-off-by: Tingmao Wang <m@maowtm.org>
Assisted-by: GitHub-Copilot:claude-opus-4.7 copilot-review
Link: https://patch.msgid.link/364fbd08081318d64bc23049d3a7721f0a3a3624.1781228815.git.m@maowtm.org
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:23 +02:00
Tingmao Wang
c7d1c54edf
selftests/landlock: Add tests for quiet flag with fs rules
Test various interactions of the quiet flag with filesystem rules:
- Non-optional access (tested with open and rename).
- Optional access (tested with truncate and ioctl).
- Behaviour around mounts matches with normal Landlock rules.
- Behaviour around disconnected directories matches with normal Landlock
  rules (test expected behaviour of 9a868cdbe66a ("landlock: Fix
  handling of disconnected directories") applied to the collected quiet
  flag).
- Multiple layers works as expected.

Assisted-by: GitHub-Copilot:claude-opus-4.6 copilot-review
Signed-off-by: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/0f304507dd3ebccc753e1580456bdfc909012357.1781228815.git.m@maowtm.org
[mic: Fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:23 +02:00
Tingmao Wang
73c2f82b32
selftests/landlock: Replace hard-coded 16 with a constant
The next commit will reuse this number.  Make it a shared constant to
future-proof changes.

Signed-off-by: Tingmao Wang <m@maowtm.org>
Link: https://patch.msgid.link/eff35caa9b4ac51aa83a88d67c4dd67f4f8b3a4a.1781228815.git.m@maowtm.org
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:22 +02:00
Tingmao Wang
29752205db
landlock: Add API support and docs for the quiet flags
Adds the UAPI for the quiet flags feature (but not the implementation
yet).

Even though currently LANDLOCK_ADD_RULE_QUIET only affects audit
logging, in the future this can also be used as part of a supervisor
mechanism, where it will also suppress denial notifications on a
per-object basis.  Thus the name is deliberately generic, as opposed to
e.g. LANDLOCK_ADD_RULE_LOG_QUIET.

According to pahole, even after adding the struct access_masks
quiet_masks in struct landlock_hierarchy, the u32 log_* bitfield still
only has a size of 2 bytes, so there's minimal wasted space.

Assisted-by: GitHub-Copilot:claude-opus-4.8
Signed-off-by: Tingmao Wang <m@maowtm.org>
[mic: Update date, fix comment formatting]
Link: https://patch.msgid.link/031184748a8e74c0bb02f1fa13d7a3f10918c627.1781228815.git.m@maowtm.org
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-14 20:17:19 +02:00
Matthieu Buffet
cf393de90f
selftests/landlock: Add tests for UDP send
Add tests specific to UDP sendmsg() in the protocol_* variants to ensure
behaviour is consistent across AF_INET, AF_INET6 and AF_UNIX.

Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://patch.msgid.link/20260611162107.49278-5-matthieu@buffet.re
[mic: Fix comment formatting, rebase]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:07 +02:00
Matthieu Buffet
42afa5c467
selftests/landlock: Add tests for UDP bind/connect
Make basic changes to the existing bind() and connect() test suite to
cover UDP restriction.

Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://patch.msgid.link/20260611162107.49278-4-matthieu@buffet.re
[mic: Update audit.connect_bound, fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:06 +02:00
Matthieu Buffet
e61247a2e6
landlock: Add UDP send+connect access control
Add support for a second fine-grained UDP access right.
LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP controls the ability to set the
remote port of a socket (via connect()) and to specify an explicit
destination when sending a datagram, to override any remote peer set on
a UDP socket (e.g. in sendto() or sendmsg()).  It will be useful for
applications that send datagrams, and for some servers too (those
creating per-client sockets, which want to receive traffic only from a
specific address).

Similarly as for bind(), this access control is performed when
configuring sockets, not in hot code paths.

Add detection of when autobind is about to be required, and deny the
operation if the process would not be allowed to call bind(0)
explicitly. Autobind can only be performed in udp_lib_get_port() from
code paths already controlled by LSM hooks: when connect()ing, sending a
first datagram, and in some splice() EOF edge case which, afaiu, can
only happen after a remote peer has been set. This invariant needs to be
preserved to keep bind policies actually enforced.

Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://patch.msgid.link/20260611162107.49278-3-matthieu@buffet.re
[mic: Add quick return for non-sandboxed tasks, fix sa_family
dereferencing, fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:04 +02:00
Matthieu Buffet
9a8ed15ce2
landlock: Add UDP bind() access control
Add support for a first fine-grained UDP access right.
LANDLOCK_ACCESS_NET_BIND_UDP controls the ability to set the local port
of a UDP socket (via bind()). It will be useful for servers (to start
receiving datagrams), and for some clients that need to use a specific
source port (e.g. mDNS requires to use port 5353)

For obvious performance concerns, access control is only enforced when
configuring sockets, not when using them for common send/recv
operations.

Bump ABI to allow userspace to detect and use this new right.

Signed-off-by: Matthieu Buffet <matthieu@buffet.re>
Link: https://patch.msgid.link/20260611162107.49278-2-matthieu@buffet.re
[mic: Fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:04 +02:00
Maximilian Heyne
0302cd72fe
selftests/landlock: Explicitly disable audit in teardowns
I'm seeing sporadic selftest failures, such as

  #  RUN           scoped_audit.connect_to_child ...
  # scoped_abstract_unix_test.c:314:connect_to_child:Expected 0 (0) == records.access (8)
  # connect_to_child: Test failed
  #          FAIL  scoped_audit.connect_to_child
  not ok 19 scoped_audit.connect_to_child

This seems similar to what commit 3647a4977f ("selftests/landlock:
Drain stale audit records on init") tried to fix. However, the added
drain loop is not effective. When setting the AUDIT_STATUS_PID, the
kauditd_thread is woken up starting to send messages from the hold queue
to the netlink. Depending on scheduling of this kthread not all messages
might be send via the netlink in the 1 us interval.

Therefore, instead of trying to drain the queue, let's just disable
audit when running non-audit tests or more precisely disable it after
audit-tests. This way we won't generate any new audit message that could
interfere with the other tests.

The comment saying that on process exit audit will be disabled is wrong.
The closed file descriptor just causes an auditd_reset(), not a
disablement. So future messages will be queued in the hold queue.

Cc: stable@vger.kernel.org
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Signed-off-by: Maximilian Heyne <mheyne@amazon.de>
Link: https://patch.msgid.link/20260529-welsh-nagoya-b4d9ca60@mheyne-amazon
[mic: Fix FD leak, update subject, call audit_cleanup() in audit_exec teardown]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:03 +02:00
Bryam Vargas
76579d09be
selftests/landlock: Test SCOPE_SIGNAL on the SIGIO/fowner pgid path
Add regression tests for the LANDLOCK_SCOPE_SIGNAL handling of the
asynchronous SIGIO delivery path (fcntl(F_SETOWN)) with a process-group
owner.

sigio_to_pgid_members covers the bypass: a sandboxed process at the head
of its process group's PGID hlist (the default after fork()) arms
F_SETOWN(-pgrp) + O_ASYNC and triggers the fan-out; the in-domain owner
must be signaled (proving the trigger fired) while the non-sandboxed
member of the group, outside the domain, must not.

sigio_to_pgid_self covers the same-process guarantee: the owner is
registered from a sandboxed non-leader thread, whose domain differs from
the thread-group leader the kernel signals for a process-group owner.
That leader belongs to the owner's own process and must still be
signaled.

Without the fix the first test sees the out-of-domain member signaled
and the second sees the owner's own leader denied.

Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://patch.msgid.link/43370e89f7a896a583bf33d1cd171d02630e61bf.1780614610.git.hexlabsecurity@proton.me
[mic: Fix comment]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:15:00 +02:00
Mickaël Salaün
d936e1a917
landlock: Set audit_net.sk for socket access checks
Set audit_net.sk in current_check_access_socket() to provide the socket
object to audit_log_lsm_data().  This makes Landlock consistent with
AppArmor, which always sets .sk for socket operations, and with
SELinux's generic socket permission checks.

The socket's local and foreign address information (laddr, lport, faddr,
fport) is logged by the shared lsm_audit.c infrastructure when the
socket has bound or connected state.  Fields with zero values are
suppressed by print_ipv4_addr()/print_ipv6_addr(), so the audit output
is unchanged for the common case of bind denials on unbound sockets.
For connect denials after a prior bind, the bound local address (laddr,
lport) appears before the existing sockaddr fields (daddr, dest).

No existing fields are removed or reordered, and the new field names
(laddr, lport, faddr, fport) are standard audit fields already emitted
by other LSMs through the same lsm_audit.c code path.

Add a connect_tcp_bound audit test that binds to an allowed port and
then connects to a denied one, verifying that the denial record reports
laddr/lport from the bound socket in addition to the connect
destination.

Cc: Günther Noack <gnoack@google.com>
Cc: Tingmao Wang <m@maowtm.org>
Cc: stable@vger.kernel.org
Fixes: 9f74411a40 ("landlock: Log TCP bind and connect denials")
Link: https://patch.msgid.link/20260612172757.1003481-1-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-06-13 23:14:56 +02:00
Mickaël Salaün
d8dfb4c7fa
selftests/landlock: Increase default audit socket timeout
matches_log_fs() and other audit_match_record() callers intermittently
return -EAGAIN under heavy debug configs (KASAN, lockdep).  The audit
record delivery pipeline is asynchronous: landlock_log_denial() queues
the record to audit_queue, and kauditd_thread dequeues and delivers via
netlink.  Under debug configs, kauditd scheduling between
audit_log_end() and netlink_unicast() can exceed a syscall round trip
(more than 1 usec), which was the value of the socket timeout used for
the recvfrom() calls.

The observed failure [1] is an EAGAIN error code (-11) which means that
the access record had not arrived within the 1 usec timeout of
recvfrom().  The expected record does arrive, but only after
matches_log_fs() has already returned.  It is then consumed by a later
audit_count_records() call, making records.access == 1 instead of 0.

Switch the default socket timeout to the slow value (1 second) so all
audit_match_record() callers wait long enough for kauditd delivery, and
lower it to the fast value (1 usec) only on the two paths that expect no
record: audit_count_records() and the expected_domain_id == 0 probe in
matches_log_domain_deallocated().  audit_init() drains stale records
with the fast timeout (terminating on -EAGAIN once the backlog is empty)
and switches to the patient default before returning.  1 second gives
~10x margin over the observed maximum (~100 ms, while the happy path is
~23 us).

Rename the timeval constants to reflect their new roles:
- audit_tv_dom_drop (1 second) -> audit_tv_default: default socket
  timeout, patient enough for asynchronous kauditd delivery.
- audit_tv_default (1 usec) -> audit_tv_fast: fast timeout for paths
  that expect no record (drain, audit_count_records(), probes).

Invert the conditional in matches_log_domain_deallocated().  Check
setsockopt returns on both the lower and restore paths; preserve the
first error via !err when the restore fails after a prior error so the
actionable return code is not masked by a bookkeeping failure.

Cc: Günther Noack <gnoack@google.com>
Cc: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Cc: stable@vger.kernel.org
Depends-on: 07c2572a87 ("selftests/landlock: Skip stale records in audit_match_record()")
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Reported-by: Günther Noack <gnoack3000@gmail.com>
Closes: https://lore.kernel.org/r/20260402.eb5c4e85f472@gnoack.org [1]
Reported-by: kernel test robot <oliver.sang@intel.com>
Closes: https://lore.kernel.org/oe-lkp/202605111649.a8b30a62-lkp@intel.com
Closes: https://lore.kernel.org/oe-lkp/202604300436.a07fae12-lkp@intel.com
Tested-by: Günther Noack <gnoack3000@gmail.com>
Link: https://patch.msgid.link/20260513105112.140137-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-05-21 19:32:13 +02:00
Mickaël Salaün
26679fad81
selftests/landlock: Filter dealloc records in audit_count_records()
audit_count_records() counts both AUDIT_LANDLOCK_DOMAIN allocation and
deallocation records in records.domain .  Domain deallocation is tied to
asynchronous credential freeing via kworker threads
(landlock_put_ruleset_deferred), so the dealloc record can arrive after
the drain in audit_init() and after the preceding audit_match_record()
call.  This causes flaky failures in tests that assert an exact
records.domain count: a stale dealloc record from a previous test's
domain inflates the count by one.

Observed on x86_64 under build configurations that delay the kworker
firing the dealloc callback (e.g. coverage instrumentation): the
audit_layout1 tests in fs_test.c intermittently saw records.domain == 2
where 1 was expected.  The fix is in the shared helper, so those
existing checks become robust without needing a fs_test.c edit.

Filter audit_count_records() with a regex to skip records containing
deallocation status.  The remaining domain records (allocation, emitted
synchronously during landlock_log_denial()) are deterministic.
Deallocation records are already tested explicitly via
matches_log_domain_deallocated() in audit_test.c, which uses its own
domain-ID-based filtering and longer timeout.

With this filter in place, re-add the records.domain == 0 checks that
were removed in commit 3647a4977f ("selftests/landlock: Drain stale
audit records on init") as a workaround for this race.

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Depends-on: 07c2572a87 ("selftests/landlock: Skip stale records in audit_match_record()")
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Tested-by: Günther Noack <gnoack3000@gmail.com>
Link: https://patch.msgid.link/20260513105112.140137-1-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-05-21 19:32:11 +02:00
Günther Noack
dc75f89046
selftests/landlock: Simplify ruleset creation and enforcement in fs_test
* Add enforce_fs() for defining and enforcing a ruleset in one step
* In some places, dropped "ASSERT_LE(0, fd)" checks after
  create_ruleset() call -- create_ruleset() already checks that.
* In some places, rename "file_fd" to "fd" if it is not needed to
  disambiguate any more.

Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260327164838.38231-12-gnoack3000@gmail.com
[mic: Tweak subjet]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:10 +02:00
Günther Noack
f433fd3fa2
selftests/landlock: Check that coredump sockets stay unrestricted
Even when a process is restricted with the new
LANDLOCK_ACCESS_FS_RESOLVE_UNIX right, the kernel can continue writing
its coredump to the configured coredump socket.

In the test, we create a local server and rewire the system to write
coredumps into it.  We then create a child process within a Landlock
domain where LANDLOCK_ACCESS_FS_RESOLVE_UNIX is restricted and make
the process crash.  The test uses SO_PEERCRED to check that the
connecting client process is the expected one.

Includes a fix by Mickaël Salaün for setting the EUID to 0 (see [1]).

Link[1]: https://lore.kernel.org/all/20260218.ohth8theu8Yi@digikod.net/
Suggested-by: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260327164838.38231-11-gnoack3000@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:10 +02:00
Günther Noack
0f42f5be0b
selftests/landlock: Audit test for LANDLOCK_ACCESS_FS_RESOLVE_UNIX
Add an audit test to check that Landlock denials from
LANDLOCK_ACCESS_FS_RESOLVE_UNIX result in audit logs in the expected
format.  (There is one audit test for each filesystem access right, so
we should add one for LANDLOCK_ACCESS_FS_RESOLVE_UNIX as well.)

Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260327164838.38231-10-gnoack3000@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:09 +02:00
Günther Noack
9da41c65c9
selftests/landlock: Test LANDLOCK_ACCESS_FS_RESOLVE_UNIX
* Extract common helpers from an existing IOCTL test that
  also uses pathname unix(7) sockets.
* These tests use the common scoped domains fixture which is also used
  in other Landlock scoping tests and which was used in Tingmao Wang's
  earlier patch set in [1].

These tests exercise the cross product of the following scenarios:

* Stream connect(), Datagram connect(), Datagram sendmsg() and
  Seqpacket connect().
* Child-to-parent and parent-to-child communication
* The Landlock policy configuration as listed in the scoped_domains
  fixture.
  * In the default variant, Landlock domains are only placed where
    prescribed in the fixture.
  * In the "ALL_DOMAINS" variant, Landlock domains are also placed in
    the places where the fixture says to omit them, but with a
    LANDLOCK_RULE_PATH_BENEATH that allows connection.

Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Tingmao Wang <m@maowtm.org>
Cc: Mickaël Salaün <mic@digikod.net>
Link[1]: https://lore.kernel.org/all/53b9883648225d5a08e82d2636ab0b4fda003bc9.1767115163.git.m@maowtm.org/
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260327164838.38231-9-gnoack3000@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:09 +02:00
Günther Noack
db8201a3fa
selftests/landlock: Replace access_fs_16 with ACCESS_ALL in fs_test
The access_fs_16 variable was originally intended to stay frozen at 16
access rights so that audit tests would not need updating when new
access rights are added.  Now that we have 17 access rights, the name
is confusing.

Replace all uses of access_fs_16 with ACCESS_ALL and delete the
variable.

Suggested-by: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260327164838.38231-8-gnoack3000@gmail.com
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:08 +02:00
Günther Noack
ae97330d1b
landlock: Control pathname UNIX domain socket resolution by path
* Add a new access right LANDLOCK_ACCESS_FS_RESOLVE_UNIX, which
  controls the lookup operations for named UNIX domain sockets.  The
  resolution happens during connect() and sendmsg() (depending on
  socket type).
* Change access_mask_t from u16 to u32 (see below)
* Hook into the path lookup in unix_find_bsd() in af_unix.c, using a
  LSM hook.  Make policy decisions based on the new access rights
* Increment the Landlock ABI version.
* Minor test adaptations to keep the tests working.
* Document the design rationale for scoped access rights,
  and cross-reference it from the header documentation.

With this access right, access is granted if either of the following
conditions is met:

* The target socket's filesystem path was allow-listed using a
  LANDLOCK_RULE_PATH_BENEATH rule, *or*:
* The target socket was created in the same Landlock domain in which
  LANDLOCK_ACCESS_FS_RESOLVE_UNIX was restricted.

In case of a denial, connect() and sendmsg() return EACCES, which is
the same error as it is returned if the user does not have the write
bit in the traditional UNIX file system permissions of that file.

The access_mask_t type grows from u16 to u32 to make space for the new
access right.  This also doubles the size of struct layer_access_masks
from 32 byte to 64 byte.  To avoid memory layout inconsistencies between
architectures (especially m68k), pack and align struct access_masks [2].

Document the (possible future) interaction between scoped flags and
other access rights in struct landlock_ruleset_attr, and summarize the
rationale, as discussed in code review leading up to [3].

This feature was created with substantial discussion and input from
Justin Suess, Tingmao Wang and Mickaël Salaün.

Cc: Tingmao Wang <m@maowtm.org>
Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Kuniyuki Iwashima <kuniyu@google.com>
Suggested-by: Jann Horn <jannh@google.com>
Link[1]: https://github.com/landlock-lsm/linux/issues/36
Link[2]: https://lore.kernel.org/all/20260401.Re1Eesu1Yaij@digikod.net/
Link[3]: https://lore.kernel.org/all/20260205.8531e4005118@gnoack.org/
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://lore.kernel.org/r/20260327164838.38231-5-gnoack3000@gmail.com
[mic: Fix kernel-doc formatting, pack and align access_masks]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:06 +02:00
Mickaël Salaün
a060ac0b8c
selftests/landlock: Fix format warning for __u64 in net_test
On architectures where __u64 is unsigned long (e.g. powerpc64), using
%llx to format a __u64 triggers a -Wformat warning because %llx expects
unsigned long long.  Cast the argument to unsigned long long.

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: a549d055a2 ("selftests/landlock: Add network tests")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/r/202604020206.62zgOTeP-lkp@intel.com/
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260402192608.1458252-6-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:03 +02:00
Mickaël Salaün
07c2572a87
selftests/landlock: Skip stale records in audit_match_record()
Domain deallocation records are emitted asynchronously from kworker
threads (via free_ruleset_work()).  Stale deallocation records from a
previous test can arrive during the current test's deallocation read
loop and be picked up by audit_match_record() instead of the expected
record, causing a domain ID mismatch.  The audit.layers test (which
creates 16 nested domains) is particularly vulnerable because it reads
16 deallocation records in sequence, providing a large window for stale
records to interleave.

The same issue affects audit_flags.signal, where deallocation records
from a previous test (audit.layers) can leak into the next test and be
picked up by audit_match_record() instead of the expected record.

Fix this by continuing to read records when the type matches but the
content pattern does not.  Stale records are silently consumed, and the
loop only stops when both type and pattern match (or the socket times
out with -EAGAIN).

Additionally, extend matches_log_domain_deallocated() with an
expected_domain_id parameter.  When set, the regex pattern includes the
specific domain ID as a literal hex value, so that deallocation records
for a different domain do not match the pattern at all.  This handles
the case where the stale record has the same denial count as the
expected one (e.g. both have denials=1), which the type+pattern loop
alone cannot distinguish.  Callers that already know the expected domain
ID (from a prior denial or allocation record) now pass it to filter
precisely.

When expected_domain_id is set, matches_log_domain_deallocated() also
temporarily increases the socket timeout to audit_tv_dom_drop (1 second)
to wait for the asynchronous kworker deallocation, and restores
audit_tv_default afterward.  This removes the need for callers to manage
the timeout switch manually.

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Link: https://lore.kernel.org/r/20260402192608.1458252-5-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:02 +02:00
Mickaël Salaün
3647a4977f
selftests/landlock: Drain stale audit records on init
Non-audit Landlock tests generate audit records as side effects when
audit_enabled is non-zero (e.g. from boot configuration).  These records
accumulate in the kernel audit backlog while no audit daemon socket is
open.  When the next test opens a new netlink socket and registers as
the audit daemon, the stale backlog is delivered, causing baseline
record count checks to fail spuriously.

Fix this by draining all pending records in audit_init() right after
setting the receive timeout.  The 1-usec SO_RCVTIMEO causes audit_recv()
to return -EAGAIN once the backlog is empty, naturally terminating the
drain loop.

Domain deallocation records are emitted asynchronously from a work
queue, so they may still arrive after the drain.  Remove records.domain
== 0 checks that are not preceded by audit_match_record() calls, which
would otherwise consume stale records before the count.  Document this
constraint above audit_count_records().

Increasing the drain timeout to catch in-flight deallocation records was
considered but rejected: a longer timeout adds latency to every
audit_init() call even when no stale record is pending, and any fixed
timeout is still not guaranteed to catch all records under load.
Removing the unprotected checks is simpler and avoids the spurious
failures.

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260402192608.1458252-4-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:01 +02:00
Mickaël Salaün
9143d79033
selftests/landlock: Fix socket file descriptor leaks in audit helpers
audit_init() opens a netlink socket and configures it, but leaks the
file descriptor if audit_set_status() or setsockopt() fails.  Fix this
by jumping to an error path that closes the socket before returning.

Apply the same fix to audit_init_with_exe_filter(), which leaks the file
descriptor from audit_init() if audit_init_filter_exe() or
audit_filter_exe() fails, and to audit_cleanup(), which leaks it if
audit_init_filter_exe() fails in FIXTURE_TEARDOWN_PARENT().

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260402192608.1458252-3-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:01 +02:00
Mickaël Salaün
b566f7a4f0
selftests/landlock: Fix snprintf truncation checks in audit helpers
snprintf() returns the number of characters that would have been
written, excluding the terminating NUL byte.  When the output is
truncated, this return value equals or exceeds the buffer size.  Fix
matches_log_domain_allocated() and matches_log_domain_deallocated() to
detect truncation with ">=" instead of ">".

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: 6a500b2297 ("selftests/landlock: Add tests for audit flags and domain IDs")
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260402192608.1458252-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:00 +02:00
Mickaël Salaün
e75e38055b
landlock: Allow TSYNC with LOG_SUBDOMAINS_OFF and fd=-1
LANDLOCK_RESTRICT_SELF_TSYNC does not allow
LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF with ruleset_fd=-1, preventing
a multithreaded process from atomically propagating subdomain log muting
to all threads without creating a domain layer.  Relax the fd=-1
condition to accept TSYNC alongside LOG_SUBDOMAINS_OFF, and update the
documentation accordingly.

Add flag validation tests for all TSYNC combinations with ruleset_fd=-1,
and audit tests verifying both transition directions: muting via TSYNC
(logged to not logged) and override via TSYNC (not logged to logged).

Cc: Günther Noack <gnoack@google.com>
Cc: stable@vger.kernel.org
Fixes: 42fc7e6543 ("landlock: Multithreading support for landlock_restrict_self()")
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260407164107.2012589-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:51:00 +02:00
Mickaël Salaün
874c8f8382
landlock: Fix LOG_SUBDOMAINS_OFF inheritance across fork()
hook_cred_transfer() only copies the Landlock security blob when the
source credential has a domain.  This is inconsistent with
landlock_restrict_self() which can set LOG_SUBDOMAINS_OFF on a
credential without creating a domain (via the ruleset_fd=-1 path): the
field is committed but not preserved across fork() because the child's
prepare_creds() calls hook_cred_transfer() which skips the copy when
domain is NULL.

This breaks the documented use case where a process mutes subdomain logs
before forking sandboxed children: the children lose the muting and
their domains produce unexpected audit records.

Fix this by unconditionally copying the Landlock credential blob.

Cc: Günther Noack <gnoack@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: stable@vger.kernel.org
Fixes: ead9079f75 ("landlock: Add LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF")
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://lore.kernel.org/r/20260407164107.2012589-1-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
2026-04-07 18:50:56 +02:00