From: Justin Suess <utilityemal77@gmail.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
kpsingh@kernel.org, paul@paul-moore.com, mic@digikod.net,
viro@zeniv.linux.org.uk, brauner@kernel.org, kees@kernel.org
Cc: gnoack@google.com, jack@suse.cz, song@kernel.org,
yonghong.song@linux.dev, martin.lau@linux.dev, m@maowtm.org,
bpf@vger.kernel.org, linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org,
Justin Suess <utilityemal77@gmail.com>,
Casey Schaufler <casey@schaufler-ca.com>
Subject: [PATCH bpf-next 03/13] lsm: Add LSM hook security_bprm_enforce_policy_kptr
Date: Thu, 30 Jul 2026 22:20:36 -0400 [thread overview]
Message-ID: <20260731022047.189137-4-utilityemal77@gmail.com> (raw)
In-Reply-To: <20260731022047.189137-1-utilityemal77@gmail.com>
Add a generic LSM hook enforcing an LSM policy object on the
credentials prepared for an execution:
security_bprm_enforce_policy_kptr(lsmid, bprm, &policy, flags)
The policy object is obtained from the owning LSM through
security_policy_kptr_from_fd(), travels in that LSM's member of
union lsm_policy_kptr, and is handed back only to that same LSM: the
shim uses the same targeted dispatch by @lsmid as the policy kptr
lifetime hooks, and returns -EOPNOTSUPP when no active LSM matches.
This is the first policy operation backed by the BPF-owned LSM
kfuncs: it lets a sleepable LSM BPF program attached to
bprm_creds_for_exec() or bprm_creds_from_file() arrange for the
executed task to start confined by a policy created through the LSM's
own userspace API, e.g. a Landlock ruleset applied to a binprm. The
BPF-facing kfunc keeps the policy pointer strongly BTF-typed all the
way to the union member the implementing LSM reads back.
The hook contract is LSM agnostic: any LSM with a notion of a
per-task policy object can implement it, with its own semantics for
how the policy composes with restrictions the credentials already
carry and for the meaning of @flags, unsupported values of which it
must reject with -EINVAL. Implementations can rely on being called
only between the preparation and the commitment of the bprm's
credentials.
Like the policy kptr lifetime hooks, this hook is excluded from the
"bpf" LSM's attachment points, as the targeted dispatch makes an
attachment there unreachable.
Cc: Paul Moore <paul@paul-moore.com>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
include/linux/lsm_hook_defs.h | 2 ++
include/linux/security.h | 12 ++++++++++
kernel/bpf/bpf_lsm.c | 1 +
security/security.c | 41 +++++++++++++++++++++++++++++++++++
4 files changed, 56 insertions(+)
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 0800622e317f..a70edbd7b761 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -455,6 +455,8 @@ LSM_HOOK(int, 0, bpf_token_capable, const struct bpf_token *token, int cap)
LSM_HOOK(int, -EOPNOTSUPP, policy_kptr_from_fd, int fd,
union lsm_policy_kptr *policy)
LSM_HOOK(void, LSM_RET_VOID, policy_kptr_put, union lsm_policy_kptr *policy)
+LSM_HOOK(int, -EOPNOTSUPP, bprm_enforce_policy_kptr, struct linux_binprm *bprm,
+ union lsm_policy_kptr *policy, u32 flags)
#endif /* CONFIG_BPF_SYSCALL */
LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
diff --git a/include/linux/security.h b/include/linux/security.h
index 5017a335918c..40dfa96b6a71 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -2332,6 +2332,10 @@ extern int security_bpf_token_capable(const struct bpf_token *token, int cap);
extern int security_policy_kptr_from_fd(u64 lsmid, int fd,
union lsm_policy_kptr *policy);
extern void security_policy_kptr_put(u64 lsmid, union lsm_policy_kptr *policy);
+extern int security_bprm_enforce_policy_kptr(u64 lsmid,
+ struct linux_binprm *bprm,
+ union lsm_policy_kptr *policy,
+ u32 flags);
#else
static inline int security_bpf(int cmd, union bpf_attr *attr,
unsigned int size, bool kernel)
@@ -2396,6 +2400,14 @@ static inline void security_policy_kptr_put(u64 lsmid,
union lsm_policy_kptr *policy)
{
}
+
+static inline int security_bprm_enforce_policy_kptr(u64 lsmid,
+ struct linux_binprm *bprm,
+ union lsm_policy_kptr *policy,
+ u32 flags)
+{
+ return -EOPNOTSUPP;
+}
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_BPF_SYSCALL */
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index e9059d43e92c..d847a180489f 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -58,6 +58,7 @@ BTF_ID(func, bpf_lsm_ismaclabel)
BTF_ID(func, bpf_lsm_file_alloc_security)
BTF_ID(func, bpf_lsm_policy_kptr_from_fd)
BTF_ID(func, bpf_lsm_policy_kptr_put)
+BTF_ID(func, bpf_lsm_bprm_enforce_policy_kptr)
BTF_SET_END(bpf_lsm_disabled_hooks)
/* List of LSM hooks that should operate on 'current' cgroup regardless
diff --git a/security/security.c b/security/security.c
index fd535bd00c24..e9d8c9492bdb 100644
--- a/security/security.c
+++ b/security/security.c
@@ -5506,6 +5506,47 @@ void security_policy_kptr_put(u64 lsmid, union lsm_policy_kptr *policy)
WARN_ON_ONCE(1);
}
+/**
+ * security_bprm_enforce_policy_kptr() - Enforce a policy on exec credentials
+ * @lsmid: LSM_ID_* value of the LSM owning @policy
+ * @bprm: execution context providing the prepared credentials to restrict
+ * @policy: the policy object to enforce, in the member of the LSM
+ * identified by @lsmid
+ * @flags: LSM-specific enforcement flags
+ *
+ * Ask the LSM identified by @lsmid to restrict the credentials
+ * prepared in @bprm with @policy, so that the executed task starts
+ * confined by it. @policy must have been obtained from the same LSM
+ * with security_policy_kptr_from_fd(); the hook borrows the
+ * reference and the caller remains responsible for releasing it.
+ * Only the hook implementation of the LSM identified by @lsmid is
+ * called: an LSM never receives a policy object meant for another LSM.
+ *
+ * This hook may only be called from an exec security context where
+ * @bprm's credentials are prepared but not yet committed, i.e. from a
+ * bprm_creds_for_exec() or bprm_creds_from_file() hook.
+ *
+ * How @policy composes with restrictions the credentials already
+ * carry is defined by the implementing LSM, as is the meaning of
+ * @flags, unsupported values of which it must reject with -EINVAL.
+ *
+ * Return: Returns 0 on success, -EOPNOTSUPP if the LSM does not
+ * implement the hook, negative values on other failures.
+ */
+int security_bprm_enforce_policy_kptr(u64 lsmid, struct linux_binprm *bprm,
+ union lsm_policy_kptr *policy, u32 flags)
+{
+ struct lsm_static_call *scall;
+
+ lsm_for_each_hook(scall, bprm_enforce_policy_kptr) {
+ if (scall->hl->lsmid->id != lsmid)
+ continue;
+ return scall->hl->hook.bprm_enforce_policy_kptr(bprm, policy,
+ flags);
+ }
+ return LSM_RET_DEFAULT(bprm_enforce_policy_kptr);
+}
+
/**
* security_bpf_map_free() - Free a bpf map's LSM blob
* @map: bpf map
--
2.54.0
next prev parent reply other threads:[~2026-07-31 2:21 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 2:20 [PATCH bpf-next 00/13] BPF interface for applying Landlock rulesets Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 01/13] lsm: Add LSM hook security_policy_kptr_from_fd Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 02/13] lsm: Add LSM hook security_policy_kptr_put Justin Suess
2026-07-31 2:44 ` sashiko-bot
2026-07-31 2:20 ` Justin Suess [this message]
2026-07-31 2:20 ` [PATCH bpf-next 04/13] landlock: Expose the ruleset fd lookup to the rest of Landlock Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 05/13] landlock: Factor the credential restriction out of landlock_restrict_self() Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 06/13] landlock: Implement the LSM policy kptr hooks Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 07/13] bpf: Add the LSM policy kfunc infrastructure Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 08/13] bpf: Add the bpf_landlock_put_ruleset kfunc and ruleset destructor Justin Suess
2026-07-31 2:46 ` sashiko-bot
2026-07-31 2:20 ` [PATCH bpf-next 09/13] bpf: Add the bpf_landlock_get_ruleset_from_fd kfunc Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 10/13] bpf: Add the bpf_landlock_restrict_binprm kfunc Justin Suess
2026-07-31 2:46 ` sashiko-bot
2026-07-31 2:20 ` [PATCH bpf-next 11/13] selftests/bpf: Add tests for the Landlock policy kfuncs Justin Suess
2026-07-31 2:20 ` [PATCH bpf-next 12/13] landlock: Document the BPF kfunc interface Justin Suess
2026-07-31 2:45 ` sashiko-bot
2026-07-31 2:20 ` [PATCH bpf-next 13/13] lsm: Document the LSM policy kptr hooks Justin Suess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260731022047.189137-4-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=casey@schaufler-ca.com \
--cc=daniel@iogearbox.net \
--cc=gnoack@google.com \
--cc=jack@suse.cz \
--cc=kees@kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=martin.lau@linux.dev \
--cc=mic@digikod.net \
--cc=paul@paul-moore.com \
--cc=song@kernel.org \
--cc=viro@zeniv.linux.org.uk \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.