bpf: Add BTF_SET_START/END macros
authorJiri Olsa <jolsa@kernel.org>
Tue, 25 Aug 2020 19:21:19 +0000 (21:21 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 25 Aug 2020 22:37:41 +0000 (15:37 -0700)
Adding support to define sorted set of BTF ID values.

Following defines sorted set of BTF ID values:

  BTF_SET_START(btf_allowlist_d_path)
  BTF_ID(func, vfs_truncate)
  BTF_ID(func, vfs_fallocate)
  BTF_ID(func, dentry_open)
  BTF_ID(func, vfs_getattr)
  BTF_ID(func, filp_close)
  BTF_SET_END(btf_allowlist_d_path)

It defines following 'struct btf_id_set' variable to access
values and count:

  struct btf_id_set btf_allowlist_d_path;

Adding 'allowed' callback to struct bpf_func_proto, to allow
verifier the check on allowed callers.

Adding btf_id_set_contains function, which will be used by
allowed callbacks to verify the caller's BTF ID value is
within allowed set.

Also removing extra '\' in __BTF_ID_LIST macro.

Added BTF_SET_START_GLOBAL macro for global sets.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200825192124.710397-10-jolsa@kernel.org
include/linux/bpf.h
include/linux/btf_ids.h
kernel/bpf/btf.c
kernel/bpf/verifier.c
tools/include/linux/btf_ids.h

index 540f5e6..a6131d9 100644 (file)
@@ -317,6 +317,7 @@ struct bpf_func_proto {
                                                    * for this argument.
                                                    */
        int *ret_btf_id; /* return value btf_id */
+       bool (*allowed)(const struct bpf_prog *prog);
 };
 
 /* bpf_context is intentionally undefined structure. Pointer to bpf_context is
@@ -1878,4 +1879,7 @@ enum bpf_text_poke_type {
 int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
                       void *addr1, void *addr2);
 
+struct btf_id_set;
+bool btf_id_set_contains(struct btf_id_set *set, u32 id);
+
 #endif /* _LINUX_BPF_H */
index 4867d54..210b086 100644 (file)
@@ -3,6 +3,11 @@
 #ifndef _LINUX_BTF_IDS_H
 #define _LINUX_BTF_IDS_H
 
+struct btf_id_set {
+       u32 cnt;
+       u32 ids[];
+};
+
 #ifdef CONFIG_DEBUG_INFO_BTF
 
 #include <linux/compiler.h> /* for __PASTE */
@@ -62,7 +67,7 @@ asm(                                                  \
 ".pushsection " BTF_IDS_SECTION ",\"a\";       \n"     \
 "." #scope " " #name ";                        \n"     \
 #name ":;                                      \n"     \
-".popsection;                                  \n");   \
+".popsection;                                  \n");
 
 #define BTF_ID_LIST(name)                              \
 __BTF_ID_LIST(name, local)                             \
@@ -88,12 +93,56 @@ asm(                                                        \
 ".zero 4                                       \n"     \
 ".popsection;                                  \n");
 
+/*
+ * The BTF_SET_START/END macros pair defines sorted list of
+ * BTF IDs plus its members count, with following layout:
+ *
+ * BTF_SET_START(list)
+ * BTF_ID(type1, name1)
+ * BTF_ID(type2, name2)
+ * BTF_SET_END(list)
+ *
+ * __BTF_ID__set__list:
+ * .zero 4
+ * list:
+ * __BTF_ID__type1__name1__3:
+ * .zero 4
+ * __BTF_ID__type2__name2__4:
+ * .zero 4
+ *
+ */
+#define __BTF_SET_START(name, scope)                   \
+asm(                                                   \
+".pushsection " BTF_IDS_SECTION ",\"a\";       \n"     \
+"." #scope " __BTF_ID__set__" #name ";         \n"     \
+"__BTF_ID__set__" #name ":;                    \n"     \
+".zero 4                                       \n"     \
+".popsection;                                  \n");
+
+#define BTF_SET_START(name)                            \
+__BTF_ID_LIST(name, local)                             \
+__BTF_SET_START(name, local)
+
+#define BTF_SET_START_GLOBAL(name)                     \
+__BTF_ID_LIST(name, globl)                             \
+__BTF_SET_START(name, globl)
+
+#define BTF_SET_END(name)                              \
+asm(                                                   \
+".pushsection " BTF_IDS_SECTION ",\"a\";      \n"      \
+".size __BTF_ID__set__" #name ", .-" #name "  \n"      \
+".popsection;                                 \n");    \
+extern struct btf_id_set name;
+
 #else
 
 #define BTF_ID_LIST(name) static u32 name[5];
 #define BTF_ID(prefix, name)
 #define BTF_ID_UNUSED
 #define BTF_ID_LIST_GLOBAL(name) u32 name[1];
+#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_END(name)
 
 #endif /* CONFIG_DEBUG_INFO_BTF */
 
index df966ac..f9ac693 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/btf_ids.h>
 #include <linux/skmsg.h>
 #include <linux/perf_event.h>
+#include <linux/bsearch.h>
+#include <linux/btf_ids.h>
 #include <net/sock.h>
 
 /* BTF (BPF Type Format) is the meta data format which describes
@@ -4762,3 +4764,15 @@ u32 btf_id(const struct btf *btf)
 {
        return btf->id;
 }
+
+static int btf_id_cmp_func(const void *a, const void *b)
+{
+       const int *pa = a, *pb = b;
+
+       return *pa - *pb;
+}
+
+bool btf_id_set_contains(struct btf_id_set *set, u32 id)
+{
+       return bsearch(&id, set->ids, set->cnt, sizeof(u32), btf_id_cmp_func) != NULL;
+}
index f003cee..7e5908b 100644 (file)
@@ -4859,6 +4859,11 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
                return -EINVAL;
        }
 
+       if (fn->allowed && !fn->allowed(env->prog)) {
+               verbose(env, "helper call is not allowed in probe\n");
+               return -EINVAL;
+       }
+
        /* With LD_ABS/IND some JITs save/restore skb from r1. */
        changes_data = bpf_helper_changes_pkt_data(fn->func);
        if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
index 4867d54..210b086 100644 (file)
@@ -3,6 +3,11 @@
 #ifndef _LINUX_BTF_IDS_H
 #define _LINUX_BTF_IDS_H
 
+struct btf_id_set {
+       u32 cnt;
+       u32 ids[];
+};
+
 #ifdef CONFIG_DEBUG_INFO_BTF
 
 #include <linux/compiler.h> /* for __PASTE */
@@ -62,7 +67,7 @@ asm(                                                  \
 ".pushsection " BTF_IDS_SECTION ",\"a\";       \n"     \
 "." #scope " " #name ";                        \n"     \
 #name ":;                                      \n"     \
-".popsection;                                  \n");   \
+".popsection;                                  \n");
 
 #define BTF_ID_LIST(name)                              \
 __BTF_ID_LIST(name, local)                             \
@@ -88,12 +93,56 @@ asm(                                                        \
 ".zero 4                                       \n"     \
 ".popsection;                                  \n");
 
+/*
+ * The BTF_SET_START/END macros pair defines sorted list of
+ * BTF IDs plus its members count, with following layout:
+ *
+ * BTF_SET_START(list)
+ * BTF_ID(type1, name1)
+ * BTF_ID(type2, name2)
+ * BTF_SET_END(list)
+ *
+ * __BTF_ID__set__list:
+ * .zero 4
+ * list:
+ * __BTF_ID__type1__name1__3:
+ * .zero 4
+ * __BTF_ID__type2__name2__4:
+ * .zero 4
+ *
+ */
+#define __BTF_SET_START(name, scope)                   \
+asm(                                                   \
+".pushsection " BTF_IDS_SECTION ",\"a\";       \n"     \
+"." #scope " __BTF_ID__set__" #name ";         \n"     \
+"__BTF_ID__set__" #name ":;                    \n"     \
+".zero 4                                       \n"     \
+".popsection;                                  \n");
+
+#define BTF_SET_START(name)                            \
+__BTF_ID_LIST(name, local)                             \
+__BTF_SET_START(name, local)
+
+#define BTF_SET_START_GLOBAL(name)                     \
+__BTF_ID_LIST(name, globl)                             \
+__BTF_SET_START(name, globl)
+
+#define BTF_SET_END(name)                              \
+asm(                                                   \
+".pushsection " BTF_IDS_SECTION ",\"a\";      \n"      \
+".size __BTF_ID__set__" #name ", .-" #name "  \n"      \
+".popsection;                                 \n");    \
+extern struct btf_id_set name;
+
 #else
 
 #define BTF_ID_LIST(name) static u32 name[5];
 #define BTF_ID(prefix, name)
 #define BTF_ID_UNUSED
 #define BTF_ID_LIST_GLOBAL(name) u32 name[1];
+#define BTF_SET_START(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_START_GLOBAL(name) static struct btf_id_set name = { 0 };
+#define BTF_SET_END(name)
 
 #endif /* CONFIG_DEBUG_INFO_BTF */