[REPORT] landlock: SCOPE_SIGNAL bypass via F_SETOWN to invoker pgid -> SIGIO/SIGKILL to non-sandboxed targets

hexlabsecurity at proton.me hexlabsecurity at proton.me
Fri May 29 19:03:18 UTC 2026


Hi Mickaël,

> Could you please replace the reproducer code with a proper kselftest?
> That would need to be a new email patch (v3) [...]

Done -- v3 is a two-patch series:

  [PATCH v3 1/2] landlock: fix LANDLOCK_SCOPE_SIGNAL bypass via F_SETOWN to invoker's pgid
  [PATCH v3 2/2] selftests/landlock: test SCOPE_SIGNAL on the SIGIO/fowner pgid path

Patch 2 replaces the informal reproducer with a regression test in
scoped_signal_test.c, reusing the existing fown/SIGURG idiom. It adds
TEST(sigio_to_pgid_members): a sandboxed child at the head of its pgid hlist
arms F_SETSIG(SIGURG) / F_SETOWN(-pgrp) / O_ASYNC and triggers the fan-out; the
in-domain child must be signaled (positive control) and the non-sandboxed
parent must not.

I also added the Fixes: tag and Cc: stable that v2 was missing:

  Fixes: 18eb75f3af40 ("landlock: Always allow signals between threads of the same process")

That is where the same-thread-group exemption on the fowner path was
introduced (v6.15; backported to 6.12.y/6.13.y/6.14.y -- the original v6.12
signal scoping captured the subject unconditionally and was not affected).
The fix hunk itself is unchanged from v1/v2 and keeps Justin's Tested-by.

A/B on 6.12.90 + CONFIG_SECURITY_LANDLOCK (same .config, only the hunk
differs): without patch 1 the new test fails (the parent is signaled); with it
the test passes and the landlock signal-scoping suite is 20/20. checkpatch is
clean except one expected Reported-by/Closes warning -- the original report was
sent to security at kernel.org, so there is no public URL to point Closes: at.

Thanks,
Bryam Vargas

Independent security researcher. HEXLAB SAS (registration pending) -- Cali, Colombia.

This series fixes a LANDLOCK_SCOPE_SIGNAL bypass on the asynchronous SIGIO
(fcntl(F_SETOWN)) delivery path and adds the kselftest requested in review.

Patch 1 narrows the same-thread-group exemption in control_current_fowner()
so that F_SETOWN to a process group (or session) always captures the caller's
Landlock subject. Without it, a sandboxed task at the head of its pgid hlist
(the default position after fork()) skips the capture, and the SIGIO fan-out
reaches non-sandboxed members of the process group, defeating SCOPE_SIGNAL.
The direct kill() path (hook_task_kill) is unaffected.

Patch 2 adds a regression test to scoped_signal_test.c, replacing the informal
reproducer that previously accompanied the fix.

The defect was introduced by commit 18eb75f3af40 ("landlock: Always allow
signals between threads of the same process") in v6.15, and is present in the
stable branches that backported it (6.12.y, 6.13.y, 6.14.y).
control_current_fowner() is identical across those branches, so patch 1 applies
as-is (stable kernels before the fown_subject conversion store the domain in
landlock_file(file)->fown_domain; the exemption and the fix are the same).

A/B verified on 6.12.90 + CONFIG_SECURITY_LANDLOCK (same .config, only the fix
hunk differs):
  - without patch 1: the new test fails -- the non-sandboxed parent receives
    the signal (SCOPE_SIGNAL bypassed);
  - with patch 1: the new test passes, and the whole landlock signal-scoping
    suite passes 20/20 (no regression).

v2 -> v3:
  - patch 1: add Fixes: tag and Cc: stable; the fix hunk is unchanged from v1/v2.
  - patch 2 (new): replace the git-notes reproducer with a kselftest.
  - v1/v2 were sent to security at kernel.org (embargoed; not in a public archive).

Bryam Vargas (2):
  landlock: fix LANDLOCK_SCOPE_SIGNAL bypass via F_SETOWN to invoker's pgid
  selftests/landlock: test SCOPE_SIGNAL on the SIGIO/fowner pgid path

 security/landlock/fs.c                        | 12 +++
 .../selftests/landlock/scoped_signal_test.c   | 97 +++++++++++++++++++
 2 files changed, 109 insertions(+)

base-commit: 27fa82620cbaa89a7fc11ac3057701d598813e87




More information about the Linux-security-module-archive mailing list