bpf: Refuse caller-supplied keyrings when the bpf one is active

Nothing changes for systems that do not use the bpf keyring. Without
bpf.keyring_unsealed=1 a caller-supplied keyring behaves exactly as
before, which also lets it serve as the staging step for software
installed onto a running system whose signing key is not enrolled
anywhere yet.

Passing bpf.keyring_unsealed=1 states that the bpf keyring is the trust
anchor for this boot, so from the first program load onwards a caller-
supplied keyring is refused with -EPERM. Deriving this from the boot
flag rather than from the keyring's runtime state keeps the decision
immutable from userspace.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260828175227.1537793-3-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Daniel Borkmann 2026-08-28 19:52:18 +02:00 committed by Alexei Starovoitov
parent 264d8fd279
commit abaa0835b4
4 changed files with 26 additions and 3 deletions

View File

@ -673,6 +673,14 @@ Kernel parameters
keys. Once the keyring is restricted it becomes active
and can be used for BPF program signature verification.
Setting this also means that the bpf keyring is the
only non-system keyring a loader may select for the
rest of the boot: caller-supplied user/session
keyrings are refused with -EPERM, whether or not
provisioning actually completed. The system keyrings
stay selectable. Leaving it unset keeps the prior
behaviour, where a caller-supplied keyring is allowed.
See Documentation/bpf/signing.rst
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)

View File

@ -3821,6 +3821,7 @@ struct bpf_key {
struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags);
struct bpf_key *bpf_lookup_system_key(u64 id);
struct bpf_key *bpf_lookup_keyring(void);
bool bpf_keyring_enforced(void);
void bpf_key_put(struct bpf_key *bkey);
int bpf_verify_pkcs7_signature(const struct bpf_dynptr *data_p,
const struct bpf_dynptr *sig_p,
@ -3846,6 +3847,11 @@ static inline struct bpf_key *bpf_lookup_keyring(void)
return NULL;
}
static inline bool bpf_keyring_enforced(void)
{
return false;
}
static inline void bpf_key_put(struct bpf_key *bkey)
{
}

View File

@ -18,6 +18,11 @@ static bool bpf_keyring_unsealed __ro_after_init;
module_param_named(keyring_unsealed, bpf_keyring_unsealed, bool, 0444);
MODULE_PARM_DESC(keyring_unsealed, "Leave the bpf keyring unsealed");
bool bpf_keyring_enforced(void)
{
return bpf_keyring_unsealed;
}
struct bpf_key *bpf_lookup_keyring(void)
{
struct bpf_key *bkey;

View File

@ -21165,12 +21165,16 @@ static int bpf_prog_verify_signature(struct bpf_verifier_env *env,
if (!attr->signature_size ||
attr->signature_size > KMALLOC_MAX_CACHE_SIZE)
return -EINVAL;
if (system_keyring_id_check(attr->keyring_id) == 0)
if (system_keyring_id_check(attr->keyring_id) == 0) {
key = bpf_lookup_system_key(attr->keyring_id);
else if (attr->keyring_id == KEY_SPEC_BPF_KEYRING)
} else if (attr->keyring_id == KEY_SPEC_BPF_KEYRING) {
key = bpf_lookup_keyring();
else
} else if (bpf_keyring_enforced()) {
verbose(env, "caller-supplied keyring refused, use bpf keyring\n");
return -EPERM;
} else {
key = bpf_lookup_user_key(attr->keyring_id, 0);
}
if (!key) {
if (attr->keyring_id == KEY_SPEC_BPF_KEYRING) {
verbose(env, "the bpf keyring is empty or has not been restricted\n");