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.  Because the
return value of bpf_lookup_system_key() is now overloaded with 0 being
a legitimate built in key identifier being the same value as NULL
indicating failure, key id 0 is swizzled to -1 to distinguish it again
and swizzled back in bpf_key_put() and bpf_verify_pkcs7_signature() to
ensure correctness.

Signed-off-by: James Bottomley <james.bottom...@hansenpartnership.com>

---
v2: keep empty struct bpf_key to avoid BTF problems and swizzle 0 key id.
---
 kernel/trace/bpf_trace.c | 43 +++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index c0ccd55a4d91..7242167fd4b6 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1242,9 +1242,11 @@ 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 {
-       struct key *key;
 };
+/* conventional value to replace zero return which would become NULL */
+const u64 BUILTIN_KEY = -1LL;
 
 __bpf_kfunc_start_defs();
 
@@ -1276,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;
@@ -1289,15 +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);
-
-       return bkey;
+       return (struct bpf_key *)key_ref_to_ptr(key_ref);
 }
 
 /**
@@ -1323,18 +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;
-
-       return bkey;
+       return (struct bpf_key *)(unsigned long)(id ? id : BUILTIN_KEY);
 }
 
 /**
@@ -1346,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 (system_keyring_id_check((unsigned long)bkey->key) < 0)
-               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
@@ -1370,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 (system_keyring_id_check((unsigned long)trusted_keyring->key) < 0) {
+       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.
@@ -1383,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;
        }
@@ -1393,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);
 }
-- 
2.43.0


Reply via email to