BPF_PROG_LOAD verifies the loader signature but does not record the outcome on the prog. LSMs and audit can read attr->signature and attr->keyring_id to infer "was this signed, against which keyring", but there is no canonical state for "loader signature + map content verified". Only the in-kernel kfunc can confirm the latter. Add prog->aux->sig (verdict + keyring) and prog->aux->is_kernel, populated by bpf_prog_load before the LSM hook. Failed verifications reject the load before the hook runs, so it observes only UNSIGNED or OK. The bpf_loader_verify_metadata kfunc promotes to METADATA_VERIFIED later. Signed-off-by: KP Singh --- include/linux/bpf.h | 19 +++++++++++++++++++ kernel/bpf/syscall.c | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 11bec73db199..14f65259f414 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1656,6 +1656,20 @@ struct bpf_stream_stage { int len; }; +enum bpf_sig_verdict { + BPF_SIG_UNSIGNED = 0, + BPF_SIG_OK, /* loader signature verified */ + BPF_SIG_METADATA_VERIFIED, /* loader signature + map content 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; @@ -1698,6 +1712,11 @@ struct bpf_prog_aux { bool changes_pkt_data; bool might_sleep; bool kprobe_write_ctx; + struct { + u8 verdict; + u8 keyring; + } sig; + bool is_kernel; 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; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 630d530782fe..51fe8d77bb39 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2798,6 +2798,20 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type) } } +static enum bpf_sig_keyring bpf_classify_keyring(s32 keyring_id) +{ + switch (keyring_id) { + case 0: + return BPF_SIG_KEYRING_BUILTIN; + case (s32)(unsigned long)VERIFY_USE_SECONDARY_KEYRING: + return BPF_SIG_KEYRING_SECONDARY; + case (s32)(unsigned long)VERIFY_USE_PLATFORM_KEYRING: + return BPF_SIG_KEYRING_PLATFORM; + default: + return BPF_SIG_KEYRING_USER; + } +} + static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr, bool is_kernel) { @@ -3027,7 +3041,13 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size) err = bpf_prog_verify_signature(prog, attr, uattr.is_kernel); if (err) goto free_prog; + prog->aux->sig.verdict = BPF_SIG_OK; + prog->aux->sig.keyring = bpf_classify_keyring(attr->keyring_id); + } else { + prog->aux->sig.verdict = BPF_SIG_UNSIGNED; + prog->aux->sig.keyring = BPF_SIG_KEYRING_NONE; } + prog->aux->is_kernel = uattr.is_kernel; prog->orig_prog = NULL; prog->jited = 0; -- 2.53.0