* [RFC] landlock: clarify signal scoping for pre-existing f_owner registrations
@ 2026-11-07 4:23 Shi Lecun
2026-11-07 14:18 ` Günther Noack
0 siblings, 1 reply; 4+ messages in thread
From: Shi Lecun @ 2026-11-07 4:23 UTC (permalink / raw)
To: mic, gnoack
Cc: linux-security-module, 张锋巍(ZHANG Fengwei)
Hi Mickaël and Günther,
While investigating LANDLOCK_SCOPE_SIGNAL, I noticed that the current
documentation does not describe how signal scoping interacts with
asynchronous notifications registered before the scope is enforced.
A minimal reproducer performs the following steps as an unprivileged user:
1. Create a pipe and use fcntl(F_SETOWN) to select a same-UID process
outside the future Landlock domain as the notification recipient.
2. Configure F_SETSIG and O_ASYNC.
3. Add a Landlock layer handling LANDLOCK_SCOPE_SIGNAL.
4. Write to the pipe.
The configured signal is still delivered to the out-of-domain process.
Using F_SETSIG(SIGKILL) makes this especially visible by terminating the
recipient. In contrast:
- kill(2) after enforcing LANDLOCK_SCOPE_SIGNAL fails with EPERM;
- registering f_owner after enforcing the scope does not result in
out-of-domain signal delivery.
I reproduced this matrix on 7.2.14-arch1-1 with Landlock ABI 10 as UID
1000:
direct kill after scope victim survives
post-scope F_SETOWN victim survives
pre-scope F_SETOWN victim receives SIGKILL
FS layer, F_SETOWN, scope victim receives SIGKILL
I also inspected a local kernel tree at commit d68ce4e71248.
From security/landlock/fs.c and security/landlock/task.c, my
understanding is that hook_file_set_fowner() saves the applicable
Landlock subject when F_SETOWN is called, and
hook_file_send_sigiotask() later checks delivery using that saved
subject. If no signal-scoped domain applied at registration time, the
saved domain is NULL and later delivery is not checked against the
triggering task's newly added domain. The usual UID/EUID checks in
sigio_perm() still apply.
This also appears to be intentional and covered by the existing
fown/sandbox_after_setown variant in
tools/testing/selftests/landlock/scoped_signal_test.c, which expects a
signal to be received when F_SETOWN happened before sandboxing. I
therefore do not consider this behavior itself to be a signal-scope
bypass.
However, Documentation/userspace-api/landlock.rst currently says:
"This limits the sending of signals to target processes which run
within the same or a nested Landlock domain."
Without a lifecycle qualification, this can be read as covering every
signal delivered after the scope is enforced, including notifications
whose f_owner was registered earlier. The same section explicitly
documents the lifetime exception for previously connected UNIX sockets,
but there is no corresponding explanation for asynchronous signals.
Would it make sense to add a paragraph along these lines?
Asynchronous signal notifications associated with a file owner, such
as SIGIO and SIGURG, are checked using the Landlock context saved
when fcntl(F_SETOWN) sets the notification recipient. Adding a
LANDLOCK_SCOPE_SIGNAL restriction later does not apply that new
restriction to notifications using the previously saved context.
Sandboxes that require signal isolation should therefore enforce
the scope before untrusted code can register asynchronous
notification recipients, and account for any pre-existing
registrations on retained file descriptors.
Does this accurately describe the intended userspace semantics?
If so, I would be happy to send a documentation patch for the IPC
scoping section.
Thanks,
Shi Lecun
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] landlock: clarify signal scoping for pre-existing f_owner registrations
2026-11-07 4:23 [RFC] landlock: clarify signal scoping for pre-existing f_owner registrations Shi Lecun
@ 2026-11-07 14:18 ` Günther Noack
2026-11-08 5:50 ` [PATCH] docs: landlock: clarify F_SETOWN signal scoping Shi Lecun
0 siblings, 1 reply; 4+ messages in thread
From: Günther Noack @ 2026-11-07 14:18 UTC (permalink / raw)
To: Shi Lecun
Cc: mic, gnoack, linux-security-module,
张锋巍(ZHANG Fengwei), Bryam Vargas
Hello Shi!
On Sat, Nov 07, 2026 at 12:23:35PM +0800, Shi Lecun wrote:
> While investigating LANDLOCK_SCOPE_SIGNAL, I noticed that the current
> documentation does not describe how signal scoping interacts with
> asynchronous notifications registered before the scope is enforced.
>
> A minimal reproducer performs the following steps as an unprivileged user:
>
> 1. Create a pipe and use fcntl(F_SETOWN) to select a same-UID process
> outside the future Landlock domain as the notification recipient.
> 2. Configure F_SETSIG and O_ASYNC.
> 3. Add a Landlock layer handling LANDLOCK_SCOPE_SIGNAL.
> 4. Write to the pipe.
>
> The configured signal is still delivered to the out-of-domain process.
> Using F_SETSIG(SIGKILL) makes this especially visible by terminating the
> recipient. In contrast:
>
> - kill(2) after enforcing LANDLOCK_SCOPE_SIGNAL fails with EPERM;
> - registering f_owner after enforcing the scope does not result in
> out-of-domain signal delivery.
>
> I reproduced this matrix on 7.2.14-arch1-1 with Landlock ABI 10 as UID
> 1000:
>
> direct kill after scope victim survives
> post-scope F_SETOWN victim survives
> pre-scope F_SETOWN victim receives SIGKILL
> FS layer, F_SETOWN, scope victim receives SIGKILL
>
> I also inspected a local kernel tree at commit d68ce4e71248.
> From security/landlock/fs.c and security/landlock/task.c, my
> understanding is that hook_file_set_fowner() saves the applicable
> Landlock subject when F_SETOWN is called, and
> hook_file_send_sigiotask() later checks delivery using that saved
> subject. If no signal-scoped domain applied at registration time, the
> saved domain is NULL and later delivery is not checked against the
> triggering task's newly added domain. The usual UID/EUID checks in
> sigio_perm() still apply.
>
> This also appears to be intentional and covered by the existing
> fown/sandbox_after_setown variant in
> tools/testing/selftests/landlock/scoped_signal_test.c, which expects a
> signal to be received when F_SETOWN happened before sandboxing. I
> therefore do not consider this behavior itself to be a signal-scope
> bypass.
>
> However, Documentation/userspace-api/landlock.rst currently says:
>
> "This limits the sending of signals to target processes which run
> within the same or a nested Landlock domain."
Thanks for the investigation!
The F_SETOWN signaling restriction was not initially covered correctly
by Landlock's signal scoping support, and was discovered and fixed by
Bryam Vargas in [1].
Another signaling-related report we received was about pseudoterminals,
with a documentation patch in the same place, in [2].
It feels that in both the F_SETOWN and the PTY case, the underlying
rationale is the same though -- a signaling mechanism that was set up
prior or independent to Landlock enforcement continues to work.
> Without a lifecycle qualification, this can be read as covering every
> signal delivered after the scope is enforced, including notifications
> whose f_owner was registered earlier. The same section explicitly
> documents the lifetime exception for previously connected UNIX sockets,
> but there is no corresponding explanation for asynchronous signals.
>
> Would it make sense to add a paragraph along these lines?
>
> Asynchronous signal notifications associated with a file owner, such
> as SIGIO and SIGURG, are checked using the Landlock context saved
> when fcntl(F_SETOWN) sets the notification recipient. Adding a
> LANDLOCK_SCOPE_SIGNAL restriction later does not apply that new
> restriction to notifications using the previously saved context.
> Sandboxes that require signal isolation should therefore enforce
> the scope before untrusted code can register asynchronous
> notification recipients, and account for any pre-existing
> registrations on retained file descriptors.
>
> Does this accurately describe the intended userspace semantics?
> If so, I would be happy to send a documentation patch for the IPC
> scoping section.
Your writeup matches my understanding as well, but I am a bit worried
that these corner cases start taking more room in the documentation
than the main point of what that feature does. How about something
shorter, maybe:
For signaling of I/O availability (F_GETSIG(2const)), Landlock
checks are done with respect to the Landlock domain at the time of
fcntl(F_SETOWN).
?
It feels better to link to the existing documentation for such
features instead of trying to describe them correctly.
–Günther
[1] https://lore.kernel.org/all/cover.1780614610.git.hexlabsecurity@proton.me/
[2] https://lore.kernel.org/all/20260923163321.79770-2-clusk@northecho.dev/
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] docs: landlock: clarify F_SETOWN signal scoping
2026-11-07 14:18 ` Günther Noack
@ 2026-11-08 5:50 ` Shi Lecun
2026-11-08 16:21 ` Günther Noack
0 siblings, 1 reply; 4+ messages in thread
From: Shi Lecun @ 2026-11-08 5:50 UTC (permalink / raw)
To: Günther Noack, Mickaël Salaün
Cc: gnoack, Fengwei Zhang, Bryam Vargas, Jonathan Corbet, Shuah Khan,
Randy Dunlap, linux-security-module, linux-doc, linux-kernel
The signal scope check for asynchronous I/O notifications uses the
Landlock domain saved when fcntl(F_SETOWN) configures the recipient.
Adding LANDLOCK_SCOPE_SIGNAL later therefore does not retroactively
restrict these pre-existing registrations.
Document this boundary in the IPC scoping section and link to the fcntl
documentation for I/O availability signaling.
Link: https://lore.kernel.org/linux-security-module/20261107.2f1fa9977739@gnoack.org/
Suggested-by: Günther Noack <gnoack3000@gmail.com>
Signed-off-by: Shi Lecun <shilc2025@mail.sustech.edu.cn>
---
Documentation/userspace-api/landlock.rst | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index 3d45b956b640..cc9c5b102b8d 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -499,6 +499,10 @@ The operations which can be scoped are:
This limits the sending of signals to target processes which run within the
same or a nested Landlock domain.
+ For signaling of I/O availability (:manpage:`F_GETSIG(2const)`), Landlock
+ checks are done with respect to the Landlock domain at the time of
+ ``fcntl(F_SETOWN)``.
+
``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``
This limits the set of abstract :manpage:`unix(7)` sockets to which we can
:manpage:`connect(2)` to socket addresses which were created by a process in
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.56.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH] docs: landlock: clarify F_SETOWN signal scoping
2026-11-08 5:50 ` [PATCH] docs: landlock: clarify F_SETOWN signal scoping Shi Lecun
@ 2026-11-08 16:21 ` Günther Noack
0 siblings, 0 replies; 4+ messages in thread
From: Günther Noack @ 2026-11-08 16:21 UTC (permalink / raw)
To: Shi Lecun
Cc: Mickaël Salaün, gnoack, Fengwei Zhang, Bryam Vargas,
Jonathan Corbet, Shuah Khan, Randy Dunlap, linux-security-module,
linux-doc, linux-kernel
On Sun, Nov 08, 2026 at 01:50:48PM +0800, Shi Lecun wrote:
> The signal scope check for asynchronous I/O notifications uses the
> Landlock domain saved when fcntl(F_SETOWN) configures the recipient.
> Adding LANDLOCK_SCOPE_SIGNAL later therefore does not retroactively
> restrict these pre-existing registrations.
>
> Document this boundary in the IPC scoping section and link to the fcntl
> documentation for I/O availability signaling.
>
> Link: https://lore.kernel.org/linux-security-module/20261107.2f1fa9977739@gnoack.org/
> Suggested-by: Günther Noack <gnoack3000@gmail.com>
> Signed-off-by: Shi Lecun <shilc2025@mail.sustech.edu.cn>
> ---
> Documentation/userspace-api/landlock.rst | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
> index 3d45b956b640..cc9c5b102b8d 100644
> --- a/Documentation/userspace-api/landlock.rst
> +++ b/Documentation/userspace-api/landlock.rst
> @@ -499,6 +499,10 @@ The operations which can be scoped are:
> This limits the sending of signals to target processes which run within the
> same or a nested Landlock domain.
>
> + For signaling of I/O availability (:manpage:`F_GETSIG(2const)`), Landlock
> + checks are done with respect to the Landlock domain at the time of
> + ``fcntl(F_SETOWN)``.
> +
> ``LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET``
> This limits the set of abstract :manpage:`unix(7)` sockets to which we can
> :manpage:`connect(2)` to socket addresses which were created by a process in
>
> base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
> --
> 2.56.0
>
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Thanks, looks good!
–Günther
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-08 16:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 4:23 [RFC] landlock: clarify signal scoping for pre-existing f_owner registrations Shi Lecun
2026-11-07 14:18 ` Günther Noack
2026-11-08 5:50 ` [PATCH] docs: landlock: clarify F_SETOWN signal scoping Shi Lecun
2026-11-08 16:21 ` Günther Noack
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox