diff mbox series

[bpf-next,v4,01/10] bpf: Refactor bpf_check_mod_kfunc_call

Message ID 20211217015031.1278167-2-memxor@gmail.com
State Awaiting Upstream
Delegated to: Pablo Neira
Headers show
Series Introduce unstable CT lookup helpers | expand

Commit Message

Kumar Kartikeya Dwivedi Dec. 17, 2021, 1:50 a.m. UTC
Future commits adding more callbacks will implement the same pattern of
matching module owner of kfunc_btf_id_set, and then operating on more
sets inside the struct. Instead of having to repeat the same code of
walking over the list, lift code searching individual sets corresponding
to a owner module out into a common helper, and index into sets array.

While the btf_id_set 'set' member for check_kfunc_call wouldn't have
been NULL so far, future commits introduce sets that are optional, hence
the common code also checks whether the pointer is valid (i.e. not NULL).

Note that we must continue search on owner match and btf_id_set_contains
returning false, since more entries may have same owner (since it can be
NULL for built-in modules). To clarify this case, a comment is added, so
that future commits don't regress the search, as it was fixed recently
in commit b12f03104324 ("bpf: Fix bpf_check_mod_kfunc_call for built-in
modules").

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 include/linux/btf.h | 15 +++++++++++++--
 kernel/bpf/btf.c    | 25 +++++++++++++++++++------
 2 files changed, 32 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 0c74348cbc9d..916da2efbea8 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -320,9 +320,19 @@  static inline const char *btf_name_by_offset(const struct btf *btf,
 }
 #endif
 
+enum kfunc_btf_id_set_type {
+	BTF_SET_CHECK,
+	__BTF_SET_MAX,
+};
+
 struct kfunc_btf_id_set {
 	struct list_head list;
-	struct btf_id_set *set;
+	union {
+		struct btf_id_set *sets[__BTF_SET_MAX];
+		struct {
+			struct btf_id_set *set;
+		};
+	};
 	struct module *owner;
 };
 
@@ -361,7 +371,8 @@  static struct kfunc_btf_id_list prog_test_kfunc_list __maybe_unused;
 #endif
 
 #define DEFINE_KFUNC_BTF_ID_SET(set, name)                                     \
-	struct kfunc_btf_id_set name = { LIST_HEAD_INIT(name.list), (set),     \
+	struct kfunc_btf_id_set name = { LIST_HEAD_INIT(name.list),            \
+					 { { (set) } },                        \
 					 THIS_MODULE }
 
 #endif
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a17de71abd2e..97f6729cf23c 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6384,20 +6384,33 @@  void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
 }
 EXPORT_SYMBOL_GPL(unregister_kfunc_btf_id_set);
 
-bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id,
-			      struct module *owner)
+/* Caller must hold reference to module 'owner' */
+static bool kfunc_btf_id_set_contains(struct kfunc_btf_id_list *klist,
+				      u32 kfunc_id, struct module *owner,
+				      enum kfunc_btf_id_set_type type)
 {
 	struct kfunc_btf_id_set *s;
+	bool ret = false;
 
+	if (type >= __BTF_SET_MAX)
+		return false;
 	mutex_lock(&klist->mutex);
 	list_for_each_entry(s, &klist->list, list) {
-		if (s->owner == owner && btf_id_set_contains(s->set, kfunc_id)) {
-			mutex_unlock(&klist->mutex);
-			return true;
+		if (s->owner == owner && s->sets[type] &&
+		    btf_id_set_contains(s->sets[type], kfunc_id)) {
+			ret = true;
+			break;
 		}
+		/* continue search, since multiple sets may have same owner */
 	}
 	mutex_unlock(&klist->mutex);
-	return false;
+	return ret;
+}
+
+bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id,
+			      struct module *owner)
+{
+	return kfunc_btf_id_set_contains(klist, kfunc_id, owner, BTF_SET_CHECK);
 }
 
 #define DEFINE_KFUNC_BTF_ID_LIST(name)                                         \