Commit eae2e83e authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov

bpf: Add BTF_SET_START/END macros

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: default avatarJiri Olsa <jolsa@kernel.org>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarAndrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200825192124.710397-10-jolsa@kernel.org
parent faaf4a79
...@@ -317,6 +317,7 @@ struct bpf_func_proto { ...@@ -317,6 +317,7 @@ struct bpf_func_proto {
* for this argument. * for this argument.
*/ */
int *ret_btf_id; /* return value btf_id */ 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 /* bpf_context is intentionally undefined structure. Pointer to bpf_context is
...@@ -1878,4 +1879,7 @@ enum bpf_text_poke_type { ...@@ -1878,4 +1879,7 @@ enum bpf_text_poke_type {
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t, int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
void *addr1, void *addr2); void *addr1, void *addr2);
struct btf_id_set;
bool btf_id_set_contains(struct btf_id_set *set, u32 id);
#endif /* _LINUX_BPF_H */ #endif /* _LINUX_BPF_H */
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
#ifndef _LINUX_BTF_IDS_H #ifndef _LINUX_BTF_IDS_H
#define _LINUX_BTF_IDS_H #define _LINUX_BTF_IDS_H
struct btf_id_set {
u32 cnt;
u32 ids[];
};
#ifdef CONFIG_DEBUG_INFO_BTF #ifdef CONFIG_DEBUG_INFO_BTF
#include <linux/compiler.h> /* for __PASTE */ #include <linux/compiler.h> /* for __PASTE */
...@@ -62,7 +67,7 @@ asm( \ ...@@ -62,7 +67,7 @@ asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \ ".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
"." #scope " " #name "; \n" \ "." #scope " " #name "; \n" \
#name ":; \n" \ #name ":; \n" \
".popsection; \n"); \ ".popsection; \n");
#define BTF_ID_LIST(name) \ #define BTF_ID_LIST(name) \
__BTF_ID_LIST(name, local) \ __BTF_ID_LIST(name, local) \
...@@ -88,12 +93,56 @@ asm( \ ...@@ -88,12 +93,56 @@ asm( \
".zero 4 \n" \ ".zero 4 \n" \
".popsection; \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 #else
#define BTF_ID_LIST(name) static u32 name[5]; #define BTF_ID_LIST(name) static u32 name[5];
#define BTF_ID(prefix, name) #define BTF_ID(prefix, name)
#define BTF_ID_UNUSED #define BTF_ID_UNUSED
#define BTF_ID_LIST_GLOBAL(name) u32 name[1]; #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 */ #endif /* CONFIG_DEBUG_INFO_BTF */
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/btf_ids.h> #include <linux/btf_ids.h>
#include <linux/skmsg.h> #include <linux/skmsg.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/bsearch.h>
#include <linux/btf_ids.h>
#include <net/sock.h> #include <net/sock.h>
/* BTF (BPF Type Format) is the meta data format which describes /* BTF (BPF Type Format) is the meta data format which describes
...@@ -4762,3 +4764,15 @@ u32 btf_id(const struct btf *btf) ...@@ -4762,3 +4764,15 @@ u32 btf_id(const struct btf *btf)
{ {
return btf->id; 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;
}
...@@ -4859,6 +4859,11 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn ...@@ -4859,6 +4859,11 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
return -EINVAL; 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. */ /* With LD_ABS/IND some JITs save/restore skb from r1. */
changes_data = bpf_helper_changes_pkt_data(fn->func); changes_data = bpf_helper_changes_pkt_data(fn->func);
if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) { if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
......
...@@ -3,6 +3,11 @@ ...@@ -3,6 +3,11 @@
#ifndef _LINUX_BTF_IDS_H #ifndef _LINUX_BTF_IDS_H
#define _LINUX_BTF_IDS_H #define _LINUX_BTF_IDS_H
struct btf_id_set {
u32 cnt;
u32 ids[];
};
#ifdef CONFIG_DEBUG_INFO_BTF #ifdef CONFIG_DEBUG_INFO_BTF
#include <linux/compiler.h> /* for __PASTE */ #include <linux/compiler.h> /* for __PASTE */
...@@ -62,7 +67,7 @@ asm( \ ...@@ -62,7 +67,7 @@ asm( \
".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \ ".pushsection " BTF_IDS_SECTION ",\"a\"; \n" \
"." #scope " " #name "; \n" \ "." #scope " " #name "; \n" \
#name ":; \n" \ #name ":; \n" \
".popsection; \n"); \ ".popsection; \n");
#define BTF_ID_LIST(name) \ #define BTF_ID_LIST(name) \
__BTF_ID_LIST(name, local) \ __BTF_ID_LIST(name, local) \
...@@ -88,12 +93,56 @@ asm( \ ...@@ -88,12 +93,56 @@ asm( \
".zero 4 \n" \ ".zero 4 \n" \
".popsection; \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 #else
#define BTF_ID_LIST(name) static u32 name[5]; #define BTF_ID_LIST(name) static u32 name[5];
#define BTF_ID(prefix, name) #define BTF_ID(prefix, name)
#define BTF_ID_UNUSED #define BTF_ID_UNUSED
#define BTF_ID_LIST_GLOBAL(name) u32 name[1]; #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 */ #endif /* CONFIG_DEBUG_INFO_BTF */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment