summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorKP Singh <kpsingh@kernel.org>2026-06-05 23:35:17 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-06-05 20:33:48 -0700
commit63a673e8a4112af267106264f50584947786845a (patch)
tree8c931de054805a3f1baa3d347bb2e8eec52f3a77 /include/linux
parentba033497f16c24be2f8ee8c162895d686885f66f (diff)
downloadlwn-63a673e8a4112af267106264f50584947786845a.tar.gz
lwn-63a673e8a4112af267106264f50584947786845a.zip
bpf: Expose signature verdict via bpf_prog_aux
BPF_PROG_LOAD verifies the loader signature but does not record the outcome on the BPF program. [BPF] LSMs and audit can read attr->signature and attr->keyring_id to infer "was this signed, and if so, against which keyring". Add prog->aux->sig (verdict + keyring_{type,serial}), populated by bpf_prog_load before the LSM hook. keyring_type classifies the keyring the load referenced (builtin, secondary, platform or user), while keyring_serial records the serial of the keyring the signature was actually validated against. System keyrings carry a pseudo key pointer with no user-visible serial and are reported as 0, as are unsigned loads. Failed verifications reject the load before the hook runs, so it observes only either UNSIGNED or VERIFIED. Signed-off-by: KP Singh <kpsingh@kernel.org> Co-developed-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/r/20260605213518.544262-1-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf.h45
1 files changed, 35 insertions, 10 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 8599b451dd7a..f615b56730d2 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -32,6 +32,7 @@
#include <linux/static_call.h>
#include <linux/memcontrol.h>
#include <linux/cfi.h>
+#include <linux/key.h>
#include <asm/rqspinlock.h>
struct bpf_verifier_env;
@@ -1674,6 +1675,19 @@ struct bpf_stream_stage {
int len;
};
+enum bpf_sig_verdict {
+ BPF_SIG_UNSIGNED = 0,
+ BPF_SIG_VERIFIED,
+};
+
+enum bpf_sig_keyring {
+ BPF_SIG_KEYRING_NONE = 0,
+ BPF_SIG_KEYRING_BUILTIN,
+ BPF_SIG_KEYRING_SECONDARY,
+ BPF_SIG_KEYRING_PLATFORM,
+ BPF_SIG_KEYRING_USER,
+};
+
struct bpf_prog_aux {
atomic64_t refcnt;
u32 used_map_cnt;
@@ -1716,6 +1730,11 @@ struct bpf_prog_aux {
bool changes_pkt_data;
bool might_sleep;
bool kprobe_write_ctx;
+ struct {
+ s32 keyring_serial;
+ u8 keyring_type;
+ u8 verdict;
+ } sig;
u64 prog_array_member_cnt; /* counts how many times as member of prog_array */
struct mutex ext_mutex; /* mutex for is_extended and prog_array_member_cnt */
struct bpf_arena *arena;
@@ -3697,8 +3716,14 @@ static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
#endif /* CONFIG_BPF_SYSCALL */
#endif /* defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) */
-#if defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL)
+#ifdef CONFIG_KEYS
+struct bpf_key {
+ struct key *key;
+ bool has_ref;
+};
+#endif /* CONFIG_KEYS */
+#if defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL)
struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags);
struct bpf_key *bpf_lookup_system_key(u64 id);
void bpf_key_put(struct bpf_key *bkey);
@@ -3706,6 +3731,10 @@ int bpf_verify_pkcs7_signature(const struct bpf_dynptr *data_p,
const struct bpf_dynptr *sig_p,
struct bpf_key *trusted_keyring);
+static inline s32 bpf_key_serial(const struct bpf_key *key)
+{
+ return key->has_ref ? key->key->serial : 0;
+}
#else
static inline struct bpf_key *bpf_lookup_user_key(u32 serial, u64 flags)
{
@@ -3727,6 +3756,11 @@ static inline int bpf_verify_pkcs7_signature(const struct bpf_dynptr *data_p,
{
return -EOPNOTSUPP;
}
+
+static inline s32 bpf_key_serial(const struct bpf_key *key)
+{
+ return 0;
+}
#endif /* defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL) */
/* verifier prototypes for helper functions called from eBPF programs */
@@ -4002,15 +4036,6 @@ static inline void bpf_cgroup_atype_get(u32 attach_btf_id, int cgroup_atype) {}
static inline void bpf_cgroup_atype_put(int cgroup_atype) {}
#endif /* CONFIG_BPF_LSM */
-struct key;
-
-#ifdef CONFIG_KEYS
-struct bpf_key {
- struct key *key;
- bool has_ref;
-};
-#endif /* CONFIG_KEYS */
-
static inline bool type_is_alloc(u32 type)
{
return type & MEM_ALLOC;