Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -3656,10 +3656,7 @@ static inline void bpf_cgroup_atype_put(int cgroup_atype) {}
struct key;

#ifdef CONFIG_KEYS
struct bpf_key {
struct key *key;
bool has_ref;
};
struct bpf_key;
#endif /* CONFIG_KEYS */

static inline bool type_is_alloc(u32 type)
Expand Down
47 changes: 19 additions & 28 deletions kernel/trace/bpf_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,12 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = {
};

#ifdef CONFIG_KEYS
/* BTF requires this even if it serves no purpose */
struct bpf_key {
};
/* conventional value to replace zero return which would become NULL */
const u64 BUILTIN_KEY = -1LL;

__bpf_kfunc_start_defs();

/**
Expand Down Expand Up @@ -1272,7 +1278,6 @@ __bpf_kfunc_start_defs();
__bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags)
{
key_ref_t key_ref;
struct bpf_key *bkey;

if (flags & ~KEY_LOOKUP_ALL)
return NULL;
Expand All @@ -1285,16 +1290,7 @@ __bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags)
if (IS_ERR(key_ref))
return NULL;

bkey = kmalloc(sizeof(*bkey), GFP_KERNEL);
if (!bkey) {
key_put(key_ref_to_ptr(key_ref));
return NULL;
}

bkey->key = key_ref_to_ptr(key_ref);
bkey->has_ref = true;

return bkey;
return (struct bpf_key *)key_ref_to_ptr(key_ref);
}

/**
Expand All @@ -1320,19 +1316,10 @@ __bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags)
*/
__bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id)
{
struct bpf_key *bkey;

if (system_keyring_id_check(id) < 0)
return NULL;

bkey = kmalloc(sizeof(*bkey), GFP_ATOMIC);
if (!bkey)
return NULL;

bkey->key = (struct key *)(unsigned long)id;
bkey->has_ref = false;

return bkey;
return (struct bpf_key *)(unsigned long)(id ? id : BUILTIN_KEY);
}

/**
Expand All @@ -1344,10 +1331,11 @@ __bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id)
*/
__bpf_kfunc void bpf_key_put(struct bpf_key *bkey)
{
if (bkey->has_ref)
key_put(bkey->key);
struct key *key = (struct key *)bkey;

kfree(bkey);
if (system_keyring_id_check((unsigned long)key) < 0 &&
(unsigned long)key != BUILTIN_KEY)
key_put(key);
}

#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
Expand All @@ -1368,11 +1356,15 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
{
struct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;
struct bpf_dynptr_kern *sig_ptr = (struct bpf_dynptr_kern *)sig_p;
struct key *key = (struct key *)trusted_keyring;
const void *data, *sig;
u32 data_len, sig_len;
int ret;

if (trusted_keyring->has_ref) {
if ((unsigned long)key == BUILTIN_KEY)
key = NULL;

if (system_keyring_id_check((unsigned long)key) < 0) {
/*
* Do the permission check deferred in bpf_lookup_user_key().
* See bpf_lookup_user_key() for more details.
Expand All @@ -1381,7 +1373,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
* it is already done by keyring_search() called by
* find_asymmetric_key().
*/
ret = key_validate(trusted_keyring->key);
ret = key_validate(key);
if (ret < 0)
return ret;
}
Expand All @@ -1391,8 +1383,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
sig_len = __bpf_dynptr_size(sig_ptr);
sig = __bpf_dynptr_data(sig_ptr, sig_len);

return verify_pkcs7_signature(data, data_len, sig, sig_len,
trusted_keyring->key,
return verify_pkcs7_signature(data, data_len, sig, sig_len, key,
VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
NULL);
}
Expand Down
Loading