Since the only consumers of struct bpf_key are bpf scripts which call the bpf kfuncs which take struct bpf_key, only the implementing functions in bpf_trace.c should be reaching inside this structure. Enforce this by making the structure opaque in the header with a body that's only defined inside bpf_trace.c Signed-off-by: James Bottomley --- include/linux/bpf.h | 5 +---- kernel/trace/bpf_trace.c | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index f9cd2164ed23..34b2df7aaf3e 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -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) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 3ae52978cae6..e7bf00d1cd05 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1242,6 +1242,11 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = { }; #ifdef CONFIG_KEYS +struct bpf_key { + struct key *key; + bool has_ref; +}; + __bpf_kfunc_start_defs(); /** -- 2.43.0 bpf_key.has_ref is used to distinguish between real key pointers and the fake key pointers that are used for system keyrings (to ensure the actual pointers to system keyrings are never visible outside certs/system_keyring.c). The keyrings subsystem has an exported function to do this, so use that in the bpf keyring code eliminating the need to store has_ref. Signed-off-by: James Bottomley --- kernel/trace/bpf_trace.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index e7bf00d1cd05..9575d018ed0f 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1244,7 +1244,6 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = { #ifdef CONFIG_KEYS struct bpf_key { struct key *key; - bool has_ref; }; __bpf_kfunc_start_defs(); @@ -1297,7 +1296,6 @@ __bpf_kfunc struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags) } bkey->key = key_ref_to_ptr(key_ref); - bkey->has_ref = true; return bkey; } @@ -1335,7 +1333,6 @@ __bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id) return NULL; bkey->key = (struct key *)(unsigned long)id; - bkey->has_ref = false; return bkey; } @@ -1349,7 +1346,7 @@ __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) + if (system_keyring_id_check((u64)bkey->key) < 0) key_put(bkey->key); kfree(bkey); @@ -1377,7 +1374,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p, u32 data_len, sig_len; int ret; - if (trusted_keyring->has_ref) { + if (system_keyring_id_check((u64)trusted_keyring->key) < 0) { /* * Do the permission check deferred in bpf_lookup_user_key(). * See bpf_lookup_user_key() for more details. -- 2.43.0 Now that struct bpf_key is an opaque structure only containing a pointer to the key, make it an alias for the key itself and thus eliminate the need to allocate and free the container. Signed-off-by: James Bottomley --- kernel/trace/bpf_trace.c | 39 +++++++++------------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 9575d018ed0f..287b69438fac 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -1242,10 +1242,6 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = { }; #ifdef CONFIG_KEYS -struct bpf_key { - struct key *key; -}; - __bpf_kfunc_start_defs(); /** @@ -1276,7 +1272,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; @@ -1289,15 +1284,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); - - return bkey; + return (struct bpf_key *)key_ref_to_ptr(key_ref); } /** @@ -1323,18 +1310,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; - - return bkey; + return (struct bpf_key *)(unsigned long)id; } /** @@ -1346,10 +1325,10 @@ __bpf_kfunc struct bpf_key *bpf_lookup_system_key(u64 id) */ __bpf_kfunc void bpf_key_put(struct bpf_key *bkey) { - if (system_keyring_id_check((u64)bkey->key) < 0) - key_put(bkey->key); + struct key *key = (struct key *)bkey; - kfree(bkey); + if (system_keyring_id_check((u64)key) < 0) + key_put(key); } #ifdef CONFIG_SYSTEM_DATA_VERIFICATION @@ -1370,11 +1349,12 @@ __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 (system_keyring_id_check((u64)trusted_keyring->key) < 0) { + if (system_keyring_id_check((u64)key) < 0) { /* * Do the permission check deferred in bpf_lookup_user_key(). * See bpf_lookup_user_key() for more details. @@ -1383,7 +1363,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; } @@ -1393,8 +1373,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); } -- 2.43.0