]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bpf: Move the signature kfuncs to helpers.c
authorKP Singh <kpsingh@kernel.org>
Sun, 14 Sep 2025 21:51:36 +0000 (23:51 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 19 Sep 2025 02:11:42 +0000 (19:11 -0700)
No functional changes, except for the addition of the headers for the
kfuncs so that they can be used for signature verification.

Signed-off-by: KP Singh <kpsingh@kernel.org>
Link: https://lore.kernel.org/r/20250914215141.15144-8-kpsingh@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/bpf.h
kernel/bpf/helpers.c
kernel/trace/bpf_trace.c

index e0c2c78a5faae87770ee21a00c2d8bf098285ef0..dfc1a27b56d5501b1dd1b5111815e589151251c5 100644 (file)
@@ -3424,6 +3424,38 @@ static inline int bpf_fd_reuseport_array_update_elem(struct bpf_map *map,
 #endif /* CONFIG_BPF_SYSCALL */
 #endif /* defined(CONFIG_INET) && defined(CONFIG_BPF_SYSCALL) */
 
+#if defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL)
+
+struct bpf_key *bpf_lookup_user_key(s32 serial, u64 flags);
+struct bpf_key *bpf_lookup_system_key(u64 id);
+void bpf_key_put(struct bpf_key *bkey);
+int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
+                              struct bpf_dynptr *sig_p,
+                              struct bpf_key *trusted_keyring);
+
+#else
+static inline struct bpf_key *bpf_lookup_user_key(u32 serial, u64 flags)
+{
+       return NULL;
+}
+
+static inline struct bpf_key *bpf_lookup_system_key(u64 id)
+{
+       return NULL;
+}
+
+static inline void bpf_key_put(struct bpf_key *bkey)
+{
+}
+
+static inline int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
+                                            struct bpf_dynptr *sig_p,
+                                            struct bpf_key *trusted_keyring)
+{
+       return -EOPNOTSUPP;
+}
+#endif /* defined(CONFIG_KEYS) && defined(CONFIG_BPF_SYSCALL) */
+
 /* verifier prototypes for helper functions called from eBPF programs */
 extern const struct bpf_func_proto bpf_map_lookup_elem_proto;
 extern const struct bpf_func_proto bpf_map_update_elem_proto;
index 51229aba53181896112092b2c16acf3d8043ad8d..ef4ede8bb74fd89dd915a63660eec84a6fea29b6 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kasan.h>
 #include <linux/bpf_verifier.h>
 #include <linux/uaccess.h>
+#include <linux/verification.h>
 
 #include "../../lib/kstrtox.h"
 
@@ -3747,6 +3748,163 @@ __bpf_kfunc int bpf_strstr(const char *s1__ign, const char *s2__ign)
 {
        return bpf_strnstr(s1__ign, s2__ign, XATTR_SIZE_MAX);
 }
+#ifdef CONFIG_KEYS
+/**
+ * bpf_lookup_user_key - lookup a key by its serial
+ * @serial: key handle serial number
+ * @flags: lookup-specific flags
+ *
+ * Search a key with a given *serial* and the provided *flags*.
+ * If found, increment the reference count of the key by one, and
+ * return it in the bpf_key structure.
+ *
+ * The bpf_key structure must be passed to bpf_key_put() when done
+ * with it, so that the key reference count is decremented and the
+ * bpf_key structure is freed.
+ *
+ * Permission checks are deferred to the time the key is used by
+ * one of the available key-specific kfuncs.
+ *
+ * Set *flags* with KEY_LOOKUP_CREATE, to attempt creating a requested
+ * special keyring (e.g. session keyring), if it doesn't yet exist.
+ * Set *flags* with KEY_LOOKUP_PARTIAL, to lookup a key without waiting
+ * for the key construction, and to retrieve uninstantiated keys (keys
+ * without data attached to them).
+ *
+ * Return: a bpf_key pointer with a valid key pointer if the key is found, a
+ *         NULL pointer otherwise.
+ */
+__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;
+
+       /*
+        * Permission check is deferred until the key is used, as the
+        * intent of the caller is unknown here.
+        */
+       key_ref = lookup_user_key(serial, flags, KEY_DEFER_PERM_CHECK);
+       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;
+}
+
+/**
+ * bpf_lookup_system_key - lookup a key by a system-defined ID
+ * @id: key ID
+ *
+ * Obtain a bpf_key structure with a key pointer set to the passed key ID.
+ * The key pointer is marked as invalid, to prevent bpf_key_put() from
+ * attempting to decrement the key reference count on that pointer. The key
+ * pointer set in such way is currently understood only by
+ * verify_pkcs7_signature().
+ *
+ * Set *id* to one of the values defined in include/linux/verification.h:
+ * 0 for the primary keyring (immutable keyring of system keys);
+ * VERIFY_USE_SECONDARY_KEYRING for both the primary and secondary keyring
+ * (where keys can be added only if they are vouched for by existing keys
+ * in those keyrings); VERIFY_USE_PLATFORM_KEYRING for the platform
+ * keyring (primarily used by the integrity subsystem to verify a kexec'ed
+ * kerned image and, possibly, the initramfs signature).
+ *
+ * Return: a bpf_key pointer with an invalid key pointer set from the
+ *         pre-determined ID on success, a NULL pointer otherwise
+ */
+__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;
+}
+
+/**
+ * bpf_key_put - decrement key reference count if key is valid and free bpf_key
+ * @bkey: bpf_key structure
+ *
+ * Decrement the reference count of the key inside *bkey*, if the pointer
+ * is valid, and free *bkey*.
+ */
+__bpf_kfunc void bpf_key_put(struct bpf_key *bkey)
+{
+       if (bkey->has_ref)
+               key_put(bkey->key);
+
+       kfree(bkey);
+}
+
+/**
+ * bpf_verify_pkcs7_signature - verify a PKCS#7 signature
+ * @data_p: data to verify
+ * @sig_p: signature of the data
+ * @trusted_keyring: keyring with keys trusted for signature verification
+ *
+ * Verify the PKCS#7 signature *sig_ptr* against the supplied *data_ptr*
+ * with keys in a keyring referenced by *trusted_keyring*.
+ *
+ * Return: 0 on success, a negative value on error.
+ */
+__bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
+                              struct bpf_dynptr *sig_p,
+                              struct bpf_key *trusted_keyring)
+{
+#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
+       struct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;
+       struct bpf_dynptr_kern *sig_ptr = (struct bpf_dynptr_kern *)sig_p;
+       const void *data, *sig;
+       u32 data_len, sig_len;
+       int ret;
+
+       if (trusted_keyring->has_ref) {
+               /*
+                * Do the permission check deferred in bpf_lookup_user_key().
+                * See bpf_lookup_user_key() for more details.
+                *
+                * A call to key_task_permission() here would be redundant, as
+                * it is already done by keyring_search() called by
+                * find_asymmetric_key().
+                */
+               ret = key_validate(trusted_keyring->key);
+               if (ret < 0)
+                       return ret;
+       }
+
+       data_len = __bpf_dynptr_size(data_ptr);
+       data = __bpf_dynptr_data(data_ptr, data_len);
+       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,
+                                     VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
+                                     NULL);
+#else
+       return -EOPNOTSUPP;
+#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
+}
+#endif /* CONFIG_KEYS */
 
 __bpf_kfunc_end_defs();
 
@@ -3788,6 +3946,14 @@ BTF_ID_FLAGS(func, bpf_throw)
 #ifdef CONFIG_BPF_EVENTS
 BTF_ID_FLAGS(func, bpf_send_signal_task, KF_TRUSTED_ARGS)
 #endif
+#ifdef CONFIG_KEYS
+BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
+BTF_ID_FLAGS(func, bpf_lookup_system_key, KF_ACQUIRE | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)
+#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
+BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)
+#endif
+#endif
 BTF_KFUNCS_END(generic_btf_ids)
 
 static const struct btf_kfunc_id_set generic_kfunc_set = {
index 606007c387c52f3ca8e412f84c09388dbdb09c76..f2360579658ead9846799a02828d6e4058511027 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/bsearch.h>
 #include <linux/sort.h>
 #include <linux/key.h>
-#include <linux/verification.h>
 #include <linux/namei.h>
 
 #include <net/bpf_sk_storage.h>
@@ -1241,188 +1240,6 @@ static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = {
        .arg1_type      = ARG_PTR_TO_CTX,
 };
 
-#ifdef CONFIG_KEYS
-__bpf_kfunc_start_defs();
-
-/**
- * bpf_lookup_user_key - lookup a key by its serial
- * @serial: key handle serial number
- * @flags: lookup-specific flags
- *
- * Search a key with a given *serial* and the provided *flags*.
- * If found, increment the reference count of the key by one, and
- * return it in the bpf_key structure.
- *
- * The bpf_key structure must be passed to bpf_key_put() when done
- * with it, so that the key reference count is decremented and the
- * bpf_key structure is freed.
- *
- * Permission checks are deferred to the time the key is used by
- * one of the available key-specific kfuncs.
- *
- * Set *flags* with KEY_LOOKUP_CREATE, to attempt creating a requested
- * special keyring (e.g. session keyring), if it doesn't yet exist.
- * Set *flags* with KEY_LOOKUP_PARTIAL, to lookup a key without waiting
- * for the key construction, and to retrieve uninstantiated keys (keys
- * without data attached to them).
- *
- * Return: a bpf_key pointer with a valid key pointer if the key is found, a
- *         NULL pointer otherwise.
- */
-__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;
-
-       /*
-        * Permission check is deferred until the key is used, as the
-        * intent of the caller is unknown here.
-        */
-       key_ref = lookup_user_key(serial, flags, KEY_DEFER_PERM_CHECK);
-       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;
-}
-
-/**
- * bpf_lookup_system_key - lookup a key by a system-defined ID
- * @id: key ID
- *
- * Obtain a bpf_key structure with a key pointer set to the passed key ID.
- * The key pointer is marked as invalid, to prevent bpf_key_put() from
- * attempting to decrement the key reference count on that pointer. The key
- * pointer set in such way is currently understood only by
- * verify_pkcs7_signature().
- *
- * Set *id* to one of the values defined in include/linux/verification.h:
- * 0 for the primary keyring (immutable keyring of system keys);
- * VERIFY_USE_SECONDARY_KEYRING for both the primary and secondary keyring
- * (where keys can be added only if they are vouched for by existing keys
- * in those keyrings); VERIFY_USE_PLATFORM_KEYRING for the platform
- * keyring (primarily used by the integrity subsystem to verify a kexec'ed
- * kerned image and, possibly, the initramfs signature).
- *
- * Return: a bpf_key pointer with an invalid key pointer set from the
- *         pre-determined ID on success, a NULL pointer otherwise
- */
-__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;
-}
-
-/**
- * bpf_key_put - decrement key reference count if key is valid and free bpf_key
- * @bkey: bpf_key structure
- *
- * Decrement the reference count of the key inside *bkey*, if the pointer
- * is valid, and free *bkey*.
- */
-__bpf_kfunc void bpf_key_put(struct bpf_key *bkey)
-{
-       if (bkey->has_ref)
-               key_put(bkey->key);
-
-       kfree(bkey);
-}
-
-#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
-/**
- * bpf_verify_pkcs7_signature - verify a PKCS#7 signature
- * @data_p: data to verify
- * @sig_p: signature of the data
- * @trusted_keyring: keyring with keys trusted for signature verification
- *
- * Verify the PKCS#7 signature *sig_ptr* against the supplied *data_ptr*
- * with keys in a keyring referenced by *trusted_keyring*.
- *
- * Return: 0 on success, a negative value on error.
- */
-__bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
-                              struct bpf_dynptr *sig_p,
-                              struct bpf_key *trusted_keyring)
-{
-       struct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;
-       struct bpf_dynptr_kern *sig_ptr = (struct bpf_dynptr_kern *)sig_p;
-       const void *data, *sig;
-       u32 data_len, sig_len;
-       int ret;
-
-       if (trusted_keyring->has_ref) {
-               /*
-                * Do the permission check deferred in bpf_lookup_user_key().
-                * See bpf_lookup_user_key() for more details.
-                *
-                * A call to key_task_permission() here would be redundant, as
-                * it is already done by keyring_search() called by
-                * find_asymmetric_key().
-                */
-               ret = key_validate(trusted_keyring->key);
-               if (ret < 0)
-                       return ret;
-       }
-
-       data_len = __bpf_dynptr_size(data_ptr);
-       data = __bpf_dynptr_data(data_ptr, data_len);
-       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,
-                                     VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
-                                     NULL);
-}
-#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */
-
-__bpf_kfunc_end_defs();
-
-BTF_KFUNCS_START(key_sig_kfunc_set)
-BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
-BTF_ID_FLAGS(func, bpf_lookup_system_key, KF_ACQUIRE | KF_RET_NULL)
-BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)
-#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
-BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)
-#endif
-BTF_KFUNCS_END(key_sig_kfunc_set)
-
-static const struct btf_kfunc_id_set bpf_key_sig_kfunc_set = {
-       .owner = THIS_MODULE,
-       .set = &key_sig_kfunc_set,
-};
-
-static int __init bpf_key_sig_kfuncs_init(void)
-{
-       return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING,
-                                        &bpf_key_sig_kfunc_set);
-}
-
-late_initcall(bpf_key_sig_kfuncs_init);
-#endif /* CONFIG_KEYS */
-
 static const struct bpf_func_proto *
 bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {