Documentation/security/landlock.rst | 25 ++ Documentation/security/lsm-development.rst | 27 ++ include/linux/lsm_hook_defs.h | 5 + include/linux/security.h | 43 +++ kernel/bpf/bpf_lsm.c | 202 +++++++++++ security/landlock/Makefile | 2 + security/landlock/bpf.c | 130 +++++++ security/landlock/bpf.h | 21 ++ security/landlock/cred.c | 116 +++++- security/landlock/cred.h | 51 +++ security/landlock/limits.h | 4 + security/landlock/ruleset.c | 2 +- security/landlock/ruleset.h | 3 + security/landlock/setup.c | 2 + security/landlock/syscalls.c | 70 +--- security/security.c | 106 ++++++ tools/testing/selftests/bpf/config | 1 + tools/testing/selftests/bpf/config.x86_64 | 2 +- .../bpf/prog_tests/lsm_policy_kfuncs.c | 329 ++++++++++++++++++ .../bpf/progs/lsm_policy_kfuncs_failure.c | 100 ++++++ .../bpf/progs/lsm_policy_kfuncs_success.c | 107 ++++++ 21 files changed, 1292 insertions(+), 56 deletions(-) create mode 100644 security/landlock/bpf.c create mode 100644 security/landlock/bpf.h create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_policy_kfuncs.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_policy_kfuncs_failure.c create mode 100644 tools/testing/selftests/bpf/progs/lsm_policy_kfuncs_success.c
Howdy,
This series lets BPF programs apply an existing, userspace-created
Landlock ruleset to a program during exec. The goal is unchanged from
the RFC [1]: BPF does not create, inspect, or mutate Landlock policy,
it only decides whether a ruleset that was already created and
validated through Landlock's existing userspace API should be applied,
based on runtime exec context.
Motivation
---
Deploying Landlock today requires the sandboxed program's
cooperation. A process can only restrict itself, so applying a
policy system-wide means wrapping every launch path with a helper
that calls landlock_restrict_self(2) before exec, and anything
spawned outside those wrappers runs unconfined. Supervising exec
from userspace instead (ptrace, seccomp user notifications) is racy
and slow. Meanwhile, the tools that do enforce system-wide policy
with BPF LSM programs today (container security agents such as
KubeArmor and Tetragon) end up reimplementing path-based access
control in BPF, fraught with horrors of path reconstruction, bind
mounts, rename races, and worse, which is exactly the problem Landlock
already solves in the kernel, with maintained and versioned semantics.
This series composes BPF and Landlock along their natural grain. The
intended deployment: a supervisor creates one ruleset per policy
class through the existing syscalls, a syscall BPF program parks
them in map kptr fields, and an LSM BPF program picks which (if
any) to apply to an execution based on its runtime context. The
policy semantics stay Landlock's; BPF contributes only the
programmable decision of when and to whom. Deciding inside the
exec path closes the race a userspace supervisor cannot: the
policy is in place before the first instruction of the new program
runs.
Addressing RFC feedback
---
The original thread at [1] received useful feedback from the BPF,
LSM and Landlock maintainers. I've hopefully been able to address
all of it here.
The interface is redesigned around the conclusions of the RFC thread.
While it's been over a week since sending [2] detailing some of the
redesign, I figure it's better to show the code.
Four main takeaways came out of the RFC feedback:
1) no kernel or BPF code may call directly into an individual LSM,
every LSM interface must go through the LSM framework.
2) LSMs interact with the kernel subsystems through LSM hooks. kfuncs
are just hooks from the LSM perspective.
3) A new map type is untenable; new maps will not be added for single
consumers. Especially because new map types become ABI.
4) We must implement a generic interface usable by all LSM, without
forgoing the type safety guarantees provided by BPF or making
a ioctl-like multiplexer.
This series does all, as proposed in [2]: the BPF subsystem owns
per-LSM, strongly typed kfuncs in kernel/bpf/bpf_lsm.c, and every
kfunc call passes through a generic LSM hook. Individual LSMs
implement ordinary LSM hooks and define no BPF interfaces at all.
The three generic hooks carry the policy reference across the LSM
boundary in union lsm_policy_kptr, tagged by the LSM_ID_* value passed
alongside. The shims dispatch only to the LSM matching that id
(following the setprocattr pattern) and return -EOPNOTSUPP when it is
compiled out or not enabled, so program loading stays independent of
the boot-time LSM configuration and kernel/bpf/ has no build-time
dependency on Landlock.
The LSM hooks
===
security_policy_kptr_from_fd(lsmid, fd, &policy)
security_policy_kptr_put(lsmid, &policy)
security_bprm_enforce_policy_kptr(lsmid, bprm, &policy, flags)
Landlock implements them as ordinary LSM hooks. The from_fd hook
validates a ruleset fd the same way as the Landlock syscalls; the
enforce hook stages a restriction on the credentials prepared for an
execution, computed by the same helpers as landlock_restrict_self(2);
and a bprm_committing_creds() hook applies it past the exec point of
no return, where nothing can fail. An execution either starts
confined by the domain or leaves the calling task untouched: a failed
execution releases the staged restriction when its aborted credentials
are freed, so no domain is created for an execution that never
happens.
The Landlock kfuncs
===
bpf_landlock_get_ruleset_from_fd(fd) KF_ACQUIRE | KF_RET_NULL
bpf_landlock_restrict_binprm(bprm, ruleset, flags)
bpf_landlock_put_ruleset(ruleset) KF_RELEASE
All sleepable-only. The acquire kfunc is exclusive to syscall
programs, which run in the context of the task whose fd table gives a
ruleset fd meaning; enforcement is exclusive to LSM programs attached
to bprm_creds_for_exec or bprm_creds_from_file; release works in both.
A kptr destructor is registered so acquired rulesets can be stashed in
ordinary map kptr fields, which is why the put hook must tolerate
non-sleepable contexts (the free is deferred).
The selftests exercise the deployment described above end to end:
a syscall program acquires the supervisor's ruleset and parks it in
a map kptr field; the LSM program takes it from the map and enforces
it on the executions it monitors. The landlock_restrict_self(2)
flags apply with their usual semantics, except
LANDLOCK_RESTRICT_SELF_TSYNC, which targets the calling threads
rather than the execution and is rejected with -EINVAL.
Changes since the RFC (quite big):
- every kfunc call now passes through a generic LSM hook; the kfuncs
moved from security/landlock to kernel/bpf/bpf_lsm.c and nothing
calls directly into Landlock
- the BPF-facing interface stays strongly typed per LSM; the tagged
union only travels across the LSM boundary. This is superior to
the void* model proposed in [2].
- BPF_MAP_TYPE_LANDLOCK_RULESET is nixed: the acquire kfunc plus an
ordinary map kptr field with a registered destructor replaces the
dedicated map type
- the whole restriction is now staged in the bprm credentials and
applied at bprm_committing_creds(), where nothing can fail, instead
of only staging the no_new_privs bit
- domain allocations on the kfunc path no longer charge the mediated
task's memcg: the enforce hook computes the restriction in a root
memcg charging scope
- LANDLOCK_RESTRICT_SELF_NO_NEW_PRIVS was split into its own series
[3] and is not carried here; this series only stages the
Landlock domain. Nothing about it was necessary for this series.
- no new UAPI: no map type, no new flag, no ABI bump (since this
series touches no Landlock ABI directly and the kfunc/syscall
side share common code paths).
Subsystem Summary
---
To LSM maintainers: This was the biggest change. There are three new
generic hooks and the union lsm_policy_kptr to abstract the lsm-specific
features declared next to lsm_prop in security.h with one member per
participating LSM. The hooks are ordinary, LSM-agnostic entry points
usable by any kernel-internal caller, with targeted dispatch by lsm_id
following the setprocattr precedent. It will return -EOPNOTSUPP when the
named LSM is compiled out or disabled. Nothing in security/ knows about
BPF, and BPF knows nothing about the enabled LSMs.
To Landlock maintainers: there is no ABI or behavior change for
existing users. The hook implementations reuse the syscall code
paths: ruleset fd validation is shared with the Landlock syscalls,
and the restriction is computed by the same helpers as
landlock_restrict_self(2), factored into prepare/apply steps so
future restrict_self features can hopefully work for both entry
points. What is new is the entry point: a restriction staged on the
bprm credentials and committed at bprm_committing_creds(), past the
point of no return. The memory accounting issue pointed out by
Mickaël is addressed as well. [4]
To BPF maintainers: BPF owns the three strongly typed kfuncs in
kernel/bpf/bpf_lsm.c, gated per program type (acquire in syscall
programs, enforcement in sleepable LSM programs on the two bprm
hooks), with a registered kptr destructor so rulesets can live in
ordinary map kptr fields. No new map type, no BPF internals touched.
kernel/bpf/ has no build-time dependency on Landlock or any other LSM
since it just calls the LSM hooks.
Patches 1-3 add the LSM hooks, 4-5 prepare Landlock (fd lookup
exposure, the restrict_self refactoring), 6 implements the hooks,
7-10 add the BPF-owned kfuncs, 11 selftests (end-to-end enforcement,
TSYNC rejection, staged-restriction replacement and discard on a
failed exec, plus six verifier rejection cases), 12-13 documentation.
Tested with a BPF CI run and manual run of the Landlock selftests.
Based on bpf-next/master, but applies cleanly to lsm/next.
[1] https://lore.kernel.org/linux-security-module/20260407200157.3874806-1-utilityemal77@gmail.com/
[2] https://lore.kernel.org/linux-security-module/al_TBtXYUNGLZHC2@zenbox/
[3] https://lore.kernel.org/linux-security-module/20260717220320.1030123-1-utilityemal77@gmail.com/
[4] https://lore.kernel.org/linux-security-module/20260701.ze4eph1eKo7a@digikod.net/
Justin Suess (13):
lsm: Add LSM hook security_policy_kptr_from_fd
lsm: Add LSM hook security_policy_kptr_put
lsm: Add LSM hook security_bprm_enforce_policy_kptr
landlock: Expose the ruleset fd lookup to the rest of Landlock
landlock: Factor the credential restriction out of
landlock_restrict_self()
landlock: Implement the LSM policy kptr hooks
bpf: Add the LSM policy kfunc infrastructure
bpf: Add the bpf_landlock_put_ruleset kfunc and ruleset destructor
bpf: Add the bpf_landlock_get_ruleset_from_fd kfunc
bpf: Add the bpf_landlock_restrict_binprm kfunc
selftests/bpf: Add tests for the Landlock policy kfuncs
landlock: Document the BPF kfunc interface
lsm: Document the LSM policy kptr hooks
Documentation/security/landlock.rst | 25 ++
Documentation/security/lsm-development.rst | 27 ++
include/linux/lsm_hook_defs.h | 5 +
include/linux/security.h | 43 +++
kernel/bpf/bpf_lsm.c | 202 +++++++++++
security/landlock/Makefile | 2 +
security/landlock/bpf.c | 130 +++++++
security/landlock/bpf.h | 21 ++
security/landlock/cred.c | 116 +++++-
security/landlock/cred.h | 51 +++
security/landlock/limits.h | 4 +
security/landlock/ruleset.c | 2 +-
security/landlock/ruleset.h | 3 +
security/landlock/setup.c | 2 +
security/landlock/syscalls.c | 70 +---
security/security.c | 106 ++++++
tools/testing/selftests/bpf/config | 1 +
tools/testing/selftests/bpf/config.x86_64 | 2 +-
.../bpf/prog_tests/lsm_policy_kfuncs.c | 329 ++++++++++++++++++
.../bpf/progs/lsm_policy_kfuncs_failure.c | 100 ++++++
.../bpf/progs/lsm_policy_kfuncs_success.c | 107 ++++++
21 files changed, 1292 insertions(+), 56 deletions(-)
create mode 100644 security/landlock/bpf.c
create mode 100644 security/landlock/bpf.h
create mode 100644 tools/testing/selftests/bpf/prog_tests/lsm_policy_kfuncs.c
create mode 100644 tools/testing/selftests/bpf/progs/lsm_policy_kfuncs_failure.c
create mode 100644 tools/testing/selftests/bpf/progs/lsm_policy_kfuncs_success.c
base-commit: f0e80dee4e32fd11e6ee1b714b75f681c7cafd3e
--
2.54.0
On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > Howdy, > > This series lets BPF programs apply an existing, userspace-created > Landlock ruleset to a program during exec. The goal is unchanged from > the RFC [1]: BPF does not create, inspect, or mutate Landlock policy, > it only decides whether a ruleset that was already created and > validated through Landlock's existing userspace API should be applied, > based on runtime exec context. > > Motivation > --- > Deploying Landlock today requires the sandboxed program's > cooperation. A process can only restrict itself, so applying a > policy system-wide means wrapping every launch path with a helper > that calls landlock_restrict_self(2) before exec, and anything > spawned outside those wrappers runs unconfined. Supervising exec > from userspace instead (ptrace, seccomp user notifications) is racy > and slow. Meanwhile, the tools that do enforce system-wide policy > with BPF LSM programs today (container security agents such as > KubeArmor and Tetragon) end up reimplementing path-based access > control in BPF, fraught with horrors of path reconstruction, bind > mounts, rename races, and worse, which is exactly the problem Landlock > already solves in the kernel, with maintained and versioned semantics. > > This series composes BPF and Landlock along their natural grain. The > intended deployment: a supervisor creates one ruleset per policy > class through the existing syscalls, a syscall BPF program parks > them in map kptr fields, and an LSM BPF program picks which (if > any) to apply to an execution based on its runtime context. The > policy semantics stay Landlock's; BPF contributes only the > programmable decision of when and to whom. Deciding inside the > exec path closes the race a userspace supervisor cannot: the > policy is in place before the first instruction of the new program > runs. Discretionary models are fun, and useful in certain situations, but they do have their limitations ;) To be fair, mandatory models have their limitations too :) I've only just barely skimmed some of the patches in this patchset, and I didn't have a chance to fully read your reply in the previous revision yet, so I wanted to get you a quick response here ... as incomplete as it may be. As you may, or may not have seen, there is currently an ongoing debate regarding the location of LSM kfuncs that will impact this patchset. Sadly, we don't appear to be approaching an agreement on this issue which introduces some additional risk to this patchset. We'll have to see how that ends up, but I just wanted you to be aware of the situation. I need to look closer at both the LSM hooks and the BPF kfuncs before I can really definitively comment on them. It looks like there has been some progress towards an LSM agnostic interface, but I'm concerned more work might be needed. However, as I said earlier, a closer examination is needed and perhaps that will reveal something different. It's also worth mentioning that this functionality looks an awful lot like a call to lsm_set_self_attr(LSM_ATTR_EXEC, <lsm_ctx:LSM_ID_LANDLOCK>, size, 0) with a lsm_ctx::ctx set to a policy fd. Once again, perhaps a closer inspection will reveal that it is nothing like that, but it kept popping into my head while reading things so I wanted to mention it, especially as it a lot of the framework infrastructure already exists. -- paul-moore.com
On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > [...] > As you may, or may not have seen, there is currently an ongoing debate > regarding the location of LSM kfuncs that will impact this patchset. > Sadly, we don't appear to be approaching an agreement on this issue > which introduces some additional risk to this patchset. We'll have to > see how that ends up, but I just wanted you to be aware of the > situation. Quick aside question: Would security/bpf/ be a better place for these type of kfuncs? security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c for kfuncs dealing with lsm-specific types. One issue with just security/ is it's not CONFIG_SECURITY_BPF. But security/bpf is. Right now security/bpf only has hooks.c so it's free real estate. That way things are more greppable... (important!) and we can have proper MAINTAINERS entries per file so emails get routed properly. (linux-security-module, bpf, and whatever lsm list) Justin
On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote: > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > [...] > > As you may, or may not have seen, there is currently an ongoing debate > > regarding the location of LSM kfuncs that will impact this patchset. > > Sadly, we don't appear to be approaching an agreement on this issue > > which introduces some additional risk to this patchset. We'll have to > > see how that ends up, but I just wanted you to be aware of the > > situation. > > Quick aside question: Would security/bpf/ be a better place for these > type of kfuncs? > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > for kfuncs dealing with lsm-specific types. This gets back to the other issue in the patchset that we've discussed: general LSM interfaces vs Landlock specific interfaces. There are plenty of reasons why we don't support the kernel calling directly into individual LSMs, and from my perspective this is another instance of that. Here it just happens to be that the kernel caller was written in BPF and not C (or Rust for that matter). -- paul-moore.com
On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote:
> On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote:
> > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > > [...]
> > > As you may, or may not have seen, there is currently an ongoing debate
> > > regarding the location of LSM kfuncs that will impact this patchset.
> > > Sadly, we don't appear to be approaching an agreement on this issue
> > > which introduces some additional risk to this patchset. We'll have to
> > > see how that ends up, but I just wanted you to be aware of the
> > > situation.
> >
> > Quick aside question: Would security/bpf/ be a better place for these
> > type of kfuncs?
> >
> > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs,
> > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c
> > for kfuncs dealing with lsm-specific types.
>
> This gets back to the other issue in the patchset that we've
> discussed: general LSM interfaces vs Landlock specific interfaces.
> There are plenty of reasons why we don't support the kernel calling
> directly into individual LSMs, and from my perspective this is another
I'm 100% on board with the no calling directly into individual LSMs part.
> instance of that. Here it just happens to be that the kernel caller
> was written in BPF and not C (or Rust for that matter).
The intention is the opposite. The point of the separate directory is
that the kfuncs can never call into an individual LSM, they only get
the LSM framework API in <linux/security.h>.
Every kfunc is a thin wrapper over the generic policy kptr hooks:
bpf_landlock_get_ruleset_from_fd()
-> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...)
-> Landlock's hook implementation
So kfunc -> generic lsm hook -> individual LSM, same as any other
caller in the kernel. There's no build dependency on Landlock either:
the kfuncs register under CONFIG_BPF_LSM, and if Landlock is compiled
out or not in the lsm order, the hook dispatch by lsm id misses and
the call returns -EOPNOTSUPP.
The only Landlock-specific part is what the BPF program sees: the
kfunc names and the opaque handle (an empty struct
bpf_landlock_ruleset).
Permit me to use SELinux-specific interface through LSM as an example.
The existing userspace API already has this exact pattern (partially
from [1], thanks Casey it was a great talk!):
ctx->id = LSM_ID_SELINUX;
ctx->flags = 0;
ctx->len = sizeof(struct lsm_ctx) + ctx_len;
ctx->ctx_len = ctx_len;
memcpy(ctx->ctx, "unconfined_u:unconfined_r:foo_t:s0", ctx_len);
lsm_set_self_attr(LSM_ATTR_EXEC, ctx, ctx->len, 0);
If you think about it; that's what this patch is doing!
"unconfined_u:unconfined_r:foo_t:s0" is as LSM specific as
bpf_landlock_ruleset* is.
This is a generic framework syscall, targeted at one LSM by lsm id, carrying
an LSM-specific payload. Our kptr is basically the lsm_ctx; the
difference is that the lsm id and payload type move out of runtime
fields and into the BTF type, so a mismatch fails at program load
instead of at runtime. Much better for security! (fail fast and fail
hard)
The verifier is why the lsm id can't stay runtime data the way
lsm_ctx carries it. Say LSM xyz's policy struct is protected by a
mutex (the caller must be able to sleep) while LSM abc's is accessed
under RCU. Those rules are enforced at program load time through the
KF_* annotations and argument types of the kfunc itself, so a single
generic policy kfunc can't carry both. Per-LSM kfuncs above the
generic hooks are what let the verifier *prove* each LSM's objects are
only accessed in the right context.
Userspace only gets away with the fully generic lsm_ctx because its
calling context is always the same: syscall context. BPF programs are
everywhere from syscalls to LSM hooks, so the context requirements
have to be part of the interface.
So I don't see these kfuncs as a Landlock-specific interface. They're
the same generic interface the framework already gives userspace,
with the lsm id and access rules promoted into *types* the verifier
can check at load time.
Justin
[1] https://static.sched.com/hosted_files/lssna24/1a/2024-04-LSSNA-liblsm.pdf
On Wed, Aug 5, 2026 at 8:32 PM Justin Suess <utilityemal77@gmail.com> wrote: > On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote: > > On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > [...] > > > > As you may, or may not have seen, there is currently an ongoing debate > > > > regarding the location of LSM kfuncs that will impact this patchset. > > > > Sadly, we don't appear to be approaching an agreement on this issue > > > > which introduces some additional risk to this patchset. We'll have to > > > > see how that ends up, but I just wanted you to be aware of the > > > > situation. > > > > > > Quick aside question: Would security/bpf/ be a better place for these > > > type of kfuncs? > > > > > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > > > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > > > for kfuncs dealing with lsm-specific types. > > > > This gets back to the other issue in the patchset that we've > > discussed: general LSM interfaces vs Landlock specific interfaces. > > There are plenty of reasons why we don't support the kernel calling > > directly into individual LSMs, and from my perspective this is another > > I'm 100% on board with the no calling directly into individual LSMs part. > > > instance of that. Here it just happens to be that the kernel caller > > was written in BPF and not C (or Rust for that matter). > > The intention is the opposite. The point of the separate directory is > that the kfuncs can never call into an individual LSM, they only get > the LSM framework API in <linux/security.h>. > > Every kfunc is a thin wrapper over the generic policy kptr hooks: > > bpf_landlock_get_ruleset_from_fd() > -> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...) > -> Landlock's hook implementation > > So kfunc -> generic lsm hook -> individual LSM, same as any other > caller in the kernel. Not exactly. That "bpf_*landlock*_XXX" kfuncs are a move away from an LSM agnostic API and not something we currently do in the kernel. Some will, and have, argued that this is more akin to the Landlock syscalls, but I see (at least) two problems with that comparison: the kfuncs being presented aren't syscalls, they are cross-subsystem kernel function calls; the Landlock syscalls were created in a different time, today these would need to be reframed as LSM syscalls*. (* To be clear, we're not going to remove the Landlock syscalls for all the obvious reasons, but we're also not going to support APIs like that unless we have throughly exhausted all other options.) -- paul-moore.com
On Fri, Aug 07, 2026 at 04:36:20PM -0400, Paul Moore wrote: > On Wed, Aug 5, 2026 at 8:32 PM Justin Suess <utilityemal77@gmail.com> wrote: > > On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote: > > > On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > > > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > [...] > > > > > As you may, or may not have seen, there is currently an ongoing debate > > > > > regarding the location of LSM kfuncs that will impact this patchset. > > > > > Sadly, we don't appear to be approaching an agreement on this issue > > > > > which introduces some additional risk to this patchset. We'll have to > > > > > see how that ends up, but I just wanted you to be aware of the > > > > > situation. > > > > > > > > Quick aside question: Would security/bpf/ be a better place for these > > > > type of kfuncs? > > > > > > > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > > > > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > > > > for kfuncs dealing with lsm-specific types. > > > > > > This gets back to the other issue in the patchset that we've > > > discussed: general LSM interfaces vs Landlock specific interfaces. > > > There are plenty of reasons why we don't support the kernel calling > > > directly into individual LSMs, and from my perspective this is another > > > > I'm 100% on board with the no calling directly into individual LSMs part. > > > > > instance of that. Here it just happens to be that the kernel caller > > > was written in BPF and not C (or Rust for that matter). > > > > The intention is the opposite. The point of the separate directory is > > that the kfuncs can never call into an individual LSM, they only get > > the LSM framework API in <linux/security.h>. > > > > Every kfunc is a thin wrapper over the generic policy kptr hooks: > > > > bpf_landlock_get_ruleset_from_fd() > > -> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...) > > -> Landlock's hook implementation > > > > So kfunc -> generic lsm hook -> individual LSM, same as any other > > caller in the kernel. > > Not exactly. That "bpf_*landlock*_XXX" kfuncs are a move away from an > LSM agnostic API and not something we currently do in the kernel. > Some will, and have, argued that this is more akin to the Landlock > syscalls, but I see (at least) two problems with that comparison: the > kfuncs being presented aren't syscalls, they are cross-subsystem > kernel function calls; the Landlock syscalls were created in a I see the argument for normal in-tree kernel interfaces. Unlike normal kernel interfaces, kfuncs: 1. Can exist without in-tree callers. 2. Are explicitly allowed to change or be removed at any time [1]. 3. Can't break builds or other in-tree subsystems when they do. This isn't hypothetical: the entire KF_KPTR_GET class (bpf_task_kptr_get(), bpf_cgroup_kptr_get(), the flag itself) was removed and replaced with a better abstraction within about a year of introduction. If Landlock (or any LSM) dies, there's zero uapi/in-tree cost to removing the kfuncs, unlike syscalls which are burned into the uapi forever, or ones with in-tree callers where we can break builds. I argue that the transient, low-commitment nature of kfuncs mitigates maintainability issues that arise from lsm-specific interfaces with in-tree callers. (which we are both opposed to). > different time, today these would need to be reframed as LSM > syscalls*. > LSM-specific interfaces exist both in the LSM syscalls and in my design. The only disagreement we have is the abstraction layer that the "LSM-specific" part comes into effect. 1) In the lsm syscalls, it's inside of the lsm_ctx and the LSM_ID. 2) In my design for kfuncs, it's in the function signature and the kptr types. It's fine to have binary blobs like lsm_ctx where we always assume userspace is untrusted. They can pass garbage through the syscall that we have to handle, which is expected. BPF and kfuncs are a ring-0, kernel internal interface, trusted after verification. You can't cast pointers, or deserialize them from binary blobs like lsm_ctx in BPF. The ownership and types of pointers must be verified at load time. kfuncs, their annotations, (KF_ACQUIRE/KF_RELEASE) and kptrs are the primary interface by which BPF checks correctness. An LSM-agnostic bpf_lsm_policy_from_fd(lsm_id, fd) multiplexer would lock every current and future LSM's policy object into a single set of lifetime and context rules, and would move type errors from load time to runtime. This would prove to be less maintainable, because the main way of ensuring correctness (kfunc signatures + kptr types) would be taken away. To avoid strawman style arguments, I ask what you would see as an alternative interface? Justin [1] https://docs.kernel.org/bpf/kfuncs.html > (* To be clear, we're not going to remove the Landlock syscalls for > all the obvious reasons, but we're also not going to support APIs like > that unless we have throughly exhausted all other options.) > > -- > paul-moore.com
On Fri, Aug 7, 2026 at 6:00 PM Justin Suess <utilityemal77@gmail.com> wrote: > On Fri, Aug 07, 2026 at 04:36:20PM -0400, Paul Moore wrote: > > On Wed, Aug 5, 2026 at 8:32 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote: > > > > On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > > > > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > > [...] > > > > > > As you may, or may not have seen, there is currently an ongoing debate > > > > > > regarding the location of LSM kfuncs that will impact this patchset. > > > > > > Sadly, we don't appear to be approaching an agreement on this issue > > > > > > which introduces some additional risk to this patchset. We'll have to > > > > > > see how that ends up, but I just wanted you to be aware of the > > > > > > situation. > > > > > > > > > > Quick aside question: Would security/bpf/ be a better place for these > > > > > type of kfuncs? > > > > > > > > > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > > > > > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > > > > > for kfuncs dealing with lsm-specific types. > > > > > > > > This gets back to the other issue in the patchset that we've > > > > discussed: general LSM interfaces vs Landlock specific interfaces. > > > > There are plenty of reasons why we don't support the kernel calling > > > > directly into individual LSMs, and from my perspective this is another > > > > > > I'm 100% on board with the no calling directly into individual LSMs part. > > > > > > > instance of that. Here it just happens to be that the kernel caller > > > > was written in BPF and not C (or Rust for that matter). > > > > > > The intention is the opposite. The point of the separate directory is > > > that the kfuncs can never call into an individual LSM, they only get > > > the LSM framework API in <linux/security.h>. > > > > > > Every kfunc is a thin wrapper over the generic policy kptr hooks: > > > > > > bpf_landlock_get_ruleset_from_fd() > > > -> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...) > > > -> Landlock's hook implementation > > > > > > So kfunc -> generic lsm hook -> individual LSM, same as any other > > > caller in the kernel. > > > > Not exactly. That "bpf_*landlock*_XXX" kfuncs are a move away from an > > LSM agnostic API and not something we currently do in the kernel. > > Some will, and have, argued that this is more akin to the Landlock > > syscalls, but I see (at least) two problems with that comparison: the > > kfuncs being presented aren't syscalls, they are cross-subsystem > > kernel function calls; the Landlock syscalls were created in a > I see the argument for normal in-tree kernel interfaces. > > Unlike normal kernel interfaces, kfuncs: > > 1. Can exist without in-tree callers. Yes, although I'm not sure how relevant that is to our discussion. I can say that it isn't relevant to my decisions. > 2. Are explicitly allowed to change or be removed at any time [1]. FWIW, the LSM hooks can be changed or removed at any time as well. For obvious reasons we try to avoid churn where possible, but there are plenty of cases where hooks have been modified, removed, relocated, etc. (some without our explicit permission, but that's another issue for another time). > 3. Can't break builds or other in-tree subsystems when they do. Of course. Rule #1 of any kernel subsystem is don't break the build :) > This isn't hypothetical: the entire KF_KPTR_GET class > (bpf_task_kptr_get(), bpf_cgroup_kptr_get(), the flag itself) was > removed and replaced with a better abstraction within about a year > of introduction. > > If Landlock (or any LSM) dies, there's zero uapi/in-tree cost to > removing the kfuncs, unlike syscalls which are burned into the uapi > forever, or ones with in-tree callers where we can break builds. > > I argue that the transient, low-commitment nature of kfuncs mitigates > maintainability issues that arise from lsm-specific interfaces with > in-tree callers. (which we are both opposed to). Sadly, the current situation between the BPF and LSM devs is not good, which means any discussion around LSM kfuncs has a good chance of turning ugly and something that should be relatively easy to maintain is likely to turn into a significant headache. To be clear, this doesn't mean I'm opposed to LSM kfuncs, I just don't agree that they are "low-commitment" at this point in time or in the foreseeable future. > To avoid strawman style arguments, I ask what you would see as > an alternative interface? As I've mentioned a couple of times now, you need to grant me the time to properly review your existing patches before I can comment in detail on the interface. You've been quick to post with new thoughts, ideas, arguments, etc., which is fine, but replying to them steals my time away from the very patchset you want me to review ;) It's up to you how you want to handle things, but my suggestion would be to pause some of these thoughts until I've had a chance to review your patchset in detail; then we can have a better discussion. -- paul-moore.com
On Sun, Aug 09, 2026 at 03:18:21PM -0400, Paul Moore wrote:
> On Fri, Aug 7, 2026 at 6:00 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > On Fri, Aug 07, 2026 at 04:36:20PM -0400, Paul Moore wrote:
> > > On Wed, Aug 5, 2026 at 8:32 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > > > On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote:
> > > > > On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > > > > > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote:
> > > > > > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote:
> > > > > > > [...]
> > > > > > > As you may, or may not have seen, there is currently an ongoing debate
> > > > > > > regarding the location of LSM kfuncs that will impact this patchset.
> > > > > > > Sadly, we don't appear to be approaching an agreement on this issue
> > > > > > > which introduces some additional risk to this patchset. We'll have to
> > > > > > > see how that ends up, but I just wanted you to be aware of the
> > > > > > > situation.
> > > > > >
> > > > > > Quick aside question: Would security/bpf/ be a better place for these
> > > > > > type of kfuncs?
> > > > > >
> > > > > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs,
> > > > > > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c
> > > > > > for kfuncs dealing with lsm-specific types.
> > > > >
> > > > > This gets back to the other issue in the patchset that we've
> > > > > discussed: general LSM interfaces vs Landlock specific interfaces.
> > > > > There are plenty of reasons why we don't support the kernel calling
> > > > > directly into individual LSMs, and from my perspective this is another
> > > >
> > > > I'm 100% on board with the no calling directly into individual LSMs part.
> > > >
> > > > > instance of that. Here it just happens to be that the kernel caller
> > > > > was written in BPF and not C (or Rust for that matter).
> > > >
> > > > The intention is the opposite. The point of the separate directory is
> > > > that the kfuncs can never call into an individual LSM, they only get
> > > > the LSM framework API in <linux/security.h>.
> > > >
> > > > Every kfunc is a thin wrapper over the generic policy kptr hooks:
> > > >
> > > > bpf_landlock_get_ruleset_from_fd()
> > > > -> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...)
> > > > -> Landlock's hook implementation
> > > >
> > > > So kfunc -> generic lsm hook -> individual LSM, same as any other
> > > > caller in the kernel.
> > >
> > > Not exactly. That "bpf_*landlock*_XXX" kfuncs are a move away from an
> > > LSM agnostic API and not something we currently do in the kernel.
> > > Some will, and have, argued that this is more akin to the Landlock
> > > syscalls, but I see (at least) two problems with that comparison: the
> > > kfuncs being presented aren't syscalls, they are cross-subsystem
> > > kernel function calls; the Landlock syscalls were created in a
> > I see the argument for normal in-tree kernel interfaces.
> >
> > Unlike normal kernel interfaces, kfuncs:
> >
> > 1. Can exist without in-tree callers.
>
> Yes, although I'm not sure how relevant that is to our discussion. I
> can say that it isn't relevant to my decisions.
>
> > 2. Are explicitly allowed to change or be removed at any time [1].
>
> FWIW, the LSM hooks can be changed or removed at any time as well.
> For obvious reasons we try to avoid churn where possible, but there
> are plenty of cases where hooks have been modified, removed,
> relocated, etc. (some without our explicit permission, but that's
> another issue for another time).
>
> > 3. Can't break builds or other in-tree subsystems when they do.
>
> Of course. Rule #1 of any kernel subsystem is don't break the build :)
>
> > This isn't hypothetical: the entire KF_KPTR_GET class
> > (bpf_task_kptr_get(), bpf_cgroup_kptr_get(), the flag itself) was
> > removed and replaced with a better abstraction within about a year
> > of introduction.
> >
> > If Landlock (or any LSM) dies, there's zero uapi/in-tree cost to
> > removing the kfuncs, unlike syscalls which are burned into the uapi
> > forever, or ones with in-tree callers where we can break builds.
> >
> > I argue that the transient, low-commitment nature of kfuncs mitigates
> > maintainability issues that arise from lsm-specific interfaces with
> > in-tree callers. (which we are both opposed to).
>
> Sadly, the current situation between the BPF and LSM devs is not good,
> which means any discussion around LSM kfuncs has a good chance of
> turning ugly and something that should be relatively easy to maintain
> is likely to turn into a significant headache. To be clear, this
> doesn't mean I'm opposed to LSM kfuncs, I just don't agree that they
> are "low-commitment" at this point in time or in the foreseeable
> future.
>
> > To avoid strawman style arguments, I ask what you would see as
> > an alternative interface?
>
> As I've mentioned a couple of times now, you need to grant me the time
> to properly review your existing patches before I can comment in
> detail on the interface. You've been quick to post with new thoughts,
> ideas, arguments, etc., which is fine, but replying to them steals my
> time away from the very patchset you want me to review ;)
>
> It's up to you how you want to handle things, but my suggestion would
> be to pause some of these thoughts until I've had a chance to review
> your patchset in detail; then we can have a better discussion.
>
Hi Paul,
Gonna admit I was wrong on this one. It is entirely possible to make
a generic kfunc interface for this, without it turning into an ioctl
style multiplexer either. Honestly I think it's the better design anyway.
Just took a month of staring at the code before the realization
hit me.
Since it's been about a month since the original submission, my plan is
to send a revised version based on generic kfuncs in
security/bpf_lsm_kfuncs.c, which expose no LSM-specific interface:
bpf_lsm_policy_from_fd(fd, flags) KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE
bpf_lsm_policy_acquire(struct lsm_policy_object *) KF_ACQUIRE | KF_RCU | KF_RET_NULL
bpf_lsm_policy_release(struct lsm_policy_object *) KF_RELEASE
bpf_lsm_policy_apply_bprm(struct lsm_policy_object *, bprm, flags) KF_SLEEPABLE
struct lsm_policy_object { /* initialized in LSM object structs */
u64 lsmid;
u32 type;
};
I know I said I'd hold off on revisions until your review, so if
you're already reviewing the current set (or still plan to), just
say so and I'll sit on it. Otherwise I'd rather send the new version
than have you waste time on a stale patchset, or on making a point
you've already convinced me of.
This generic design is better, and I've already experimented with
implementing the same hooks/kfuncs for AppArmor / SELinux exec-time
transitions (possible future patchsets?). This would allow writing
LSM-agnostic BPF programs (like liblsm).
Thank you so much for your feedback Paul.
Mickäel,
I think this should address your concerns about the multiplexer
design, this avoids it handily by making the rulesets/"policy object"
self-identifying so there's no need for an opcode/lsmid parameter.
There's a small lsm_policy_struct that gets embedded in the ruleset
with the lsmid already initialized, and then the original ruleset
is retrieved via container_of.
Otherwise, the semantics of the API, the flags, and implementation
are identical to this set, with the exception that ruleset
references can be taken under RCU.
Thank you for both your time and feedback,
Justin
> --
> paul-moore.com
On Sun, Aug 09, 2026 at 03:18:21PM -0400, Paul Moore wrote: > On Fri, Aug 7, 2026 at 6:00 PM Justin Suess <utilityemal77@gmail.com> wrote: > > On Fri, Aug 07, 2026 at 04:36:20PM -0400, Paul Moore wrote: > > > On Wed, Aug 5, 2026 at 8:32 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > On Wed, Aug 05, 2026 at 06:51:56PM -0400, Paul Moore wrote: > > > > > On Wed, Aug 5, 2026 at 5:37 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > > > > > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > > > [...] > > > > > > > As you may, or may not have seen, there is currently an ongoing debate > > > > > > > regarding the location of LSM kfuncs that will impact this patchset. > > > > > > > Sadly, we don't appear to be approaching an agreement on this issue > > > > > > > which introduces some additional risk to this patchset. We'll have to > > > > > > > see how that ends up, but I just wanted you to be aware of the > > > > > > > situation. > > > > > > > > > > > > Quick aside question: Would security/bpf/ be a better place for these > > > > > > type of kfuncs? > > > > > > > > > > > > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > > > > > > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > > > > > > for kfuncs dealing with lsm-specific types. > > > > > > > > > > This gets back to the other issue in the patchset that we've > > > > > discussed: general LSM interfaces vs Landlock specific interfaces. > > > > > There are plenty of reasons why we don't support the kernel calling > > > > > directly into individual LSMs, and from my perspective this is another > > > > > > > > I'm 100% on board with the no calling directly into individual LSMs part. > > > > > > > > > instance of that. Here it just happens to be that the kernel caller > > > > > was written in BPF and not C (or Rust for that matter). > > > > > > > > The intention is the opposite. The point of the separate directory is > > > > that the kfuncs can never call into an individual LSM, they only get > > > > the LSM framework API in <linux/security.h>. > > > > > > > > Every kfunc is a thin wrapper over the generic policy kptr hooks: > > > > > > > > bpf_landlock_get_ruleset_from_fd() > > > > -> security_policy_kptr_from_fd(LSM_ID_LANDLOCK, ...) > > > > -> Landlock's hook implementation > > > > > > > > So kfunc -> generic lsm hook -> individual LSM, same as any other > > > > caller in the kernel. > > > > > > Not exactly. That "bpf_*landlock*_XXX" kfuncs are a move away from an > > > LSM agnostic API and not something we currently do in the kernel. > > > Some will, and have, argued that this is more akin to the Landlock > > > syscalls, but I see (at least) two problems with that comparison: the > > > kfuncs being presented aren't syscalls, they are cross-subsystem > > > kernel function calls; the Landlock syscalls were created in a > > I see the argument for normal in-tree kernel interfaces. > > > > Unlike normal kernel interfaces, kfuncs: > > > > 1. Can exist without in-tree callers. > > Yes, although I'm not sure how relevant that is to our discussion. I > can say that it isn't relevant to my decisions. > > > 2. Are explicitly allowed to change or be removed at any time [1]. > > FWIW, the LSM hooks can be changed or removed at any time as well. > For obvious reasons we try to avoid churn where possible, but there > are plenty of cases where hooks have been modified, removed, > relocated, etc. (some without our explicit permission, but that's > another issue for another time). > > > 3. Can't break builds or other in-tree subsystems when they do. > > Of course. Rule #1 of any kernel subsystem is don't break the build :) > > > This isn't hypothetical: the entire KF_KPTR_GET class > > (bpf_task_kptr_get(), bpf_cgroup_kptr_get(), the flag itself) was > > removed and replaced with a better abstraction within about a year > > of introduction. > > > > If Landlock (or any LSM) dies, there's zero uapi/in-tree cost to > > removing the kfuncs, unlike syscalls which are burned into the uapi > > forever, or ones with in-tree callers where we can break builds. > > > > I argue that the transient, low-commitment nature of kfuncs mitigates > > maintainability issues that arise from lsm-specific interfaces with > > in-tree callers. (which we are both opposed to). > > Sadly, the current situation between the BPF and LSM devs is not good, > which means any discussion around LSM kfuncs has a good chance of > turning ugly and something that should be relatively easy to maintain > is likely to turn into a significant headache. To be clear, this > doesn't mean I'm opposed to LSM kfuncs, I just don't agree that they > are "low-commitment" at this point in time or in the foreseeable > future. > > > To avoid strawman style arguments, I ask what you would see as > > an alternative interface? > > As I've mentioned a couple of times now, you need to grant me the time > to properly review your existing patches before I can comment in > detail on the interface. You've been quick to post with new thoughts, > ideas, arguments, etc., which is fine, but replying to them steals my > time away from the very patchset you want me to review ;) > > It's up to you how you want to handle things, but my suggestion would > be to pause some of these thoughts until I've had a chance to review > your patchset in detail; then we can have a better discussion. > Apologies! I appreciate the engagement thus far, it's been helpful even if it's not 100% agreement. (wouldn't be interesting if I don't learn anything, or go back to drawing board). Especially with merge window upcoming I am sure everyone is busy. Justin > -- > paul-moore.com
On Wed, Aug 05, 2026 at 05:37:07PM -0400, Justin Suess wrote: > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > [...] > > As you may, or may not have seen, there is currently an ongoing debate > > regarding the location of LSM kfuncs that will impact this patchset. > > Sadly, we don't appear to be approaching an agreement on this issue > > which introduces some additional risk to this patchset. We'll have to > > see how that ends up, but I just wanted you to be aware of the > > situation. > > Quick aside question: Would security/bpf/ be a better place for these > type of kfuncs? > *lsm-specific kfuncs, sorry should have been more clear. Justin > security/bpf/bpf_lsm_kfuncs.c could be for LSM framework kfuncs, > and each LSM could maintain their own security/bpf/<lsm>_kfuncs.c > for kfuncs dealing with lsm-specific types. > > One issue with just security/ is it's not CONFIG_SECURITY_BPF. But > security/bpf is. Right now security/bpf only has hooks.c so it's free > real estate. > > That way things are more greppable... (important!) and we can have > proper MAINTAINERS entries per file so emails get routed properly. > > (linux-security-module, bpf, and whatever lsm list) > > Justin
On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > Howdy, > > > > This series lets BPF programs apply an existing, userspace-created > > Landlock ruleset to a program during exec. The goal is unchanged from > > the RFC [1]: BPF does not create, inspect, or mutate Landlock policy, > > it only decides whether a ruleset that was already created and > > validated through Landlock's existing userspace API should be applied, > > based on runtime exec context. > > > > Motivation > > --- > > Deploying Landlock today requires the sandboxed program's > > cooperation. A process can only restrict itself, so applying a > > policy system-wide means wrapping every launch path with a helper > > that calls landlock_restrict_self(2) before exec, and anything > > spawned outside those wrappers runs unconfined. Supervising exec > > from userspace instead (ptrace, seccomp user notifications) is racy > > and slow. Meanwhile, the tools that do enforce system-wide policy > > with BPF LSM programs today (container security agents such as > > KubeArmor and Tetragon) end up reimplementing path-based access > > control in BPF, fraught with horrors of path reconstruction, bind > > mounts, rename races, and worse, which is exactly the problem Landlock > > already solves in the kernel, with maintained and versioned semantics. > > > > This series composes BPF and Landlock along their natural grain. The > > intended deployment: a supervisor creates one ruleset per policy > > class through the existing syscalls, a syscall BPF program parks > > them in map kptr fields, and an LSM BPF program picks which (if > > any) to apply to an execution based on its runtime context. The > > policy semantics stay Landlock's; BPF contributes only the > > programmable decision of when and to whom. Deciding inside the > > exec path closes the race a userspace supervisor cannot: the > > policy is in place before the first instruction of the new program > > runs. > > Discretionary models are fun, and useful in certain situations, but > they do have their limitations ;) To be fair, mandatory models have > their limitations too :) > This series does kind of blur the lines between DAC and MAC a little... interesting thought. > I've only just barely skimmed some of the patches in this patchset, > and I didn't have a chance to fully read your reply in the previous > revision yet, so I wanted to get you a quick response here ... as > incomplete as it may be. > > As you may, or may not have seen, there is currently an ongoing debate > regarding the location of LSM kfuncs that will impact this patchset. > Sadly, we don't appear to be approaching an agreement on this issue > which introduces some additional risk to this patchset. We'll have to > see how that ends up, but I just wanted you to be aware of the > situation. > I'll hold off on further iterations until that's resolved. Moving these kfuncs anywhere fortunately amounts to a trivial cut/paste on end anyway. > I need to look closer at both the LSM hooks and the BPF kfuncs before > I can really definitively comment on them. It looks like there has > been some progress towards an LSM agnostic interface, but I'm > concerned more work might be needed. However, as I said earlier, a > closer examination is needed and perhaps that will reveal something > different. > > It's also worth mentioning that this functionality looks an awful lot > like a call to lsm_set_self_attr(LSM_ATTR_EXEC, > <lsm_ctx:LSM_ID_LANDLOCK>, size, 0) with a lsm_ctx::ctx set to a > policy fd. Once again, perhaps a closer inspection will reveal that > it is nothing like that, but it kept popping into my head while > reading things so I wanted to mention it, especially as it a lot of > the framework infrastructure already exists. They were the direct inspiration for the hooks (and set/getprocattr). Main difference being the object in the hook is a trusted kernel pointer rather than a lsm_ctx blob or fd. We can't use an fd here since the sandboxed task and supervisor don't share an fd table. I'll wait for your full review, no rush. Justin > > -- > paul-moore.com
On Fri, Jul 31, 2026 at 5:15 PM Justin Suess <utilityemal77@gmail.com> wrote: > On Fri, Jul 31, 2026 at 04:30:39PM -0400, Paul Moore wrote: > > On Thu, Jul 30, 2026 at 10:21 PM Justin Suess <utilityemal77@gmail.com> wrote: > > > > > > Howdy, > > > > > > This series lets BPF programs apply an existing, userspace-created > > > Landlock ruleset to a program during exec. The goal is unchanged from > > > the RFC [1]: BPF does not create, inspect, or mutate Landlock policy, > > > it only decides whether a ruleset that was already created and > > > validated through Landlock's existing userspace API should be applied, > > > based on runtime exec context. > > > > > > Motivation > > > --- > > > Deploying Landlock today requires the sandboxed program's > > > cooperation. A process can only restrict itself, so applying a > > > policy system-wide means wrapping every launch path with a helper > > > that calls landlock_restrict_self(2) before exec, and anything > > > spawned outside those wrappers runs unconfined. Supervising exec > > > from userspace instead (ptrace, seccomp user notifications) is racy > > > and slow. Meanwhile, the tools that do enforce system-wide policy > > > with BPF LSM programs today (container security agents such as > > > KubeArmor and Tetragon) end up reimplementing path-based access > > > control in BPF, fraught with horrors of path reconstruction, bind > > > mounts, rename races, and worse, which is exactly the problem Landlock > > > already solves in the kernel, with maintained and versioned semantics. > > > > > > This series composes BPF and Landlock along their natural grain. The > > > intended deployment: a supervisor creates one ruleset per policy > > > class through the existing syscalls, a syscall BPF program parks > > > them in map kptr fields, and an LSM BPF program picks which (if > > > any) to apply to an execution based on its runtime context. The > > > policy semantics stay Landlock's; BPF contributes only the > > > programmable decision of when and to whom. Deciding inside the > > > exec path closes the race a userspace supervisor cannot: the > > > policy is in place before the first instruction of the new program > > > runs. > > > > Discretionary models are fun, and useful in certain situations, but > > they do have their limitations ;) To be fair, mandatory models have > > their limitations too :) > > > > This series does kind of blur the lines between DAC and MAC > a little... interesting thought. > > > I've only just barely skimmed some of the patches in this patchset, > > and I didn't have a chance to fully read your reply in the previous > > revision yet, so I wanted to get you a quick response here ... as > > incomplete as it may be. > > > > As you may, or may not have seen, there is currently an ongoing debate > > regarding the location of LSM kfuncs that will impact this patchset. > > Sadly, we don't appear to be approaching an agreement on this issue > > which introduces some additional risk to this patchset. We'll have to > > see how that ends up, but I just wanted you to be aware of the > > situation. > > > > I'll hold off on further iterations until that's resolved. > > Moving these kfuncs anywhere fortunately amounts to a trivial > cut/paste on end anyway. > > > I need to look closer at both the LSM hooks and the BPF kfuncs before > > I can really definitively comment on them. It looks like there has > > been some progress towards an LSM agnostic interface, but I'm > > concerned more work might be needed. However, as I said earlier, a > > closer examination is needed and perhaps that will reveal something > > different. > > > > It's also worth mentioning that this functionality looks an awful lot > > like a call to lsm_set_self_attr(LSM_ATTR_EXEC, > > <lsm_ctx:LSM_ID_LANDLOCK>, size, 0) with a lsm_ctx::ctx set to a > > policy fd. Once again, perhaps a closer inspection will reveal that > > it is nothing like that, but it kept popping into my head while > > reading things so I wanted to mention it, especially as it a lot of > > the framework infrastructure already exists. > > They were the direct inspiration for the hooks (and set/getprocattr). > > Main difference being the object in the hook is a trusted kernel pointer > rather than a lsm_ctx blob or fd. We can't use an fd here since the > sandboxed task and supervisor don't share an fd table. > > I'll wait for your full review, no rush. I appreciate your patience, thanks. -- paul-moore.com
© 2016 - 2026 Red Hat, Inc.