Re: [PATCH bpf-next 0/2] lsm: give BPF programs a way to query locked_down state

From: Xiujianfeng

Date: Tue Aug 18 2026 - 06:55:03 EST


On 8/18/2026 12:46 PM, Justin Suess wrote:
On Tue, Aug 18, 2026 at 11:47:55AM +0800, Xiujianfeng wrote:
+cc Nicolas

On 8/15/2026 7:20 PM, Justin Suess wrote:
Howdy,

BPF programs can attach to the locked_down LSM hook and contribute a
verdict, but they have never been able to ask the locked_down question
themselves: there is no way for a program to invoke the hook and learn
whether a given operation is locked down. (i.e be a caller of
security_locked_down rather than a consumer).

Today the state has to be fed in out of band, for example userspace
reading /sys/kernel/security/lockdown and writing the result into a
map. That is a time-of-check/time-of-use race: a security_locked_down
verdict can be raised at runtime, so the cached answer can be stale
by the time the program acts on it.

Adding the bpf_security_locked_down() kfunc does not actually solve the
TOCTOU issue you mentioned. Even after bpf_security_locked_down() is
called, userspace can still change the lockdown state via /sys/kernel/
security/lockdown.

This would put it at the same raciness level as any kernel caller of
security_locked_down.

More importantly, the sysfs file is not equivalent to calling the
hook. /sys/kernel/security/lockdown reflects only the lockdown LSM's
static level.

security_locked_down() is a generic LSM hook and other
implementers of locked_down: including BPF LSM programs attached to
that hook (which is already supported) can contribute per-reason,
dynamic verdicts that never appear in sysfs. The composite answer is
only obtainable by invoking the hook, which is what this kfunc exposes.

I fail to see the necessity for a BPF program to know whether a specific
operation is locked down. The test case provided in patch 2 does not
clearly demonstrate a scenario where this is required. In my view, the
verdict should happen exactly where security_locked_down() is currently
invoked.

Elaborating a bit more on the use cases:

1. Being able to know if features LOCKDOWN_BPF_READ / LOCKDOWN_KPROBES is
locked down without a userspace hop / polling an LSM-specific interface
for error handling.

2. Use with the BPF LSM implmentations of security_locked_down, without
Lockdown even in the picture.

3. A BPF LSM can restrict access to arbritrary sensitive resources based
on the security_locked_down verdict.


I stand by my view that LSM arbitration should happen right where the action is actually executed. Wrapping it inside BPF kfuncs introduces
dangerous nested invocations between LSM and BPF. While your patch
blocks the locked_down hook from calling bpf_security_locked_down, it is
a whack-a-mole workaround and does not alter the fact of nesting itself.

Furthermore, based on the current implementation of Lockdown, integrity
is the prerequisite for confidentiality. It is designed to be coarse-
grained and does not support per-operation lockdown. The fact that LSM
BPF can already hook into locked_down seems to violate this foundational
model, this is is analogous to the bitmap implementation [1], I’m
considering whether we should restrict BPF from attaching to the
locked_down hook. Nicolas, what are your thoughts on this?

You describe a Lockdown-specific model, why should other security models /
implementations of the same hook be made to have the same semantics?

The point of the LSM hooks are to be generic.

(I have use cases that do rely on that hook; though I'm embarrased to
speak on it and it is probably abuse: I use this hook to temporarily
disable hibernation in BPF)

Justin

[1]
https://lore.kernel.org/all/20250728111517.134116-1-nik.borisov@xxxxxxxx/


Add a bpf_security_locked_down() kfunc that calls
security_locked_down() and returns its verdict, letting LSM and
syscall programs query locked_down state at decision time. Out-of-range
reasons are rejected with -EINVAL before dispatching the hook, and the
kfunc is refused to programs attached to the locked_down hook itself,
which would recurse into the dispatch. (how the obvious recursion issue
is addressed).

As this is the first pure-lsm-hook kfunc, add a new file security/lsm_kfuncs.c
to host it.

This kfunc has no reliance on / relation to the Lockdown LSM, despite the
similar naming. It is an LSM-agnostic caller of security_locked_down, and
Lockdown just happens to be the only in-tree subscriber to this hook at the
moment.

In fact, the test environment does not rely on CONFIG_SECURITY_LOCKDOWN at
all, and uses a BPF implementation of security_locked_down.

This kfunc can cause notices to be printed with kmsg if the Lockdown LSM is
enabled due to this line in security/lockdown/lockdown.c:

pr_notice_ratelimited("Lockdown: %s: %s is restricted; see man kernel_lockdown.7\n",
current->comm, lockdown_reasons[what]);

Patch 1 adds the kfunc, patch 2 the selftests. This is based on bpf-next/master, but
applies cleanly to the lsm tree.

Justin

Justin Suess (2):
lsm: add bpf_security_locked_down() kfunc
selftests/bpf: Test bpf_security_locked_down kfunc

security/Makefile | 1 +
security/lsm_kfuncs.c | 84 +++++++++++++++++++
.../selftests/bpf/prog_tests/lsm_kfuncs.c | 28 +++++++
.../testing/selftests/bpf/progs/lsm_kfuncs.c | 34 ++++++++
.../selftests/bpf/progs/lsm_kfuncs_fail.c | 26 ++++++
5 files changed, 173 insertions(+)
create mode 100644 security/lsm_kfuncs.c
create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_kfuncs.c
create mode 100644 tools/testing/selftests/bpf/progs/lsm_kfuncs.c
create mode 100644 tools/testing/selftests/bpf/progs/lsm_kfuncs_fail.c


base-commit: d82ebfc685c91e7f5623a8be949da1ddb767420b