Commit b202d844 authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov
Browse files

bpf: Remove check_kfunc_call callback and old kfunc BTF ID API



Completely remove the old code for check_kfunc_call to help it work
with modules, and also the callback itself.

The previous commit adds infrastructure to register all sets and put
them in vmlinux or module BTF, and concatenates all related sets
organized by the hook and the type. Once populated, these sets remain
immutable for the lifetime of the struct btf.

Also, since we don't need the 'owner' module anywhere when doing
check_kfunc_call, drop the 'btf_modp' module parameter from
find_kfunc_desc_btf.

Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20220114163953.1455836-4-memxor@gmail.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent dee872e1
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -573,7 +573,6 @@ struct bpf_verifier_ops {
				 const struct btf_type *t, int off, int size,
				 enum bpf_access_type atype,
				 u32 *next_btf_id);
	bool (*check_kfunc_call)(u32 kfunc_btf_id, struct module *owner);
};

struct bpf_prog_offload_ops {
@@ -1719,7 +1718,6 @@ int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
				const union bpf_attr *kattr,
				union bpf_attr __user *uattr);
bool bpf_prog_test_check_kfunc_call(u32 kfunc_id, struct module *owner);
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
		    const struct bpf_prog *prog,
		    struct bpf_insn_access_aux *info);
@@ -1971,12 +1969,6 @@ static inline int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
	return -ENOTSUPP;
}

static inline bool bpf_prog_test_check_kfunc_call(u32 kfunc_id,
						  struct module *owner)
{
	return false;
}

static inline void bpf_map_put(struct bpf_map *map)
{
}
+0 −44
Original line number Diff line number Diff line
@@ -359,48 +359,4 @@ static inline int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
}
#endif

struct kfunc_btf_id_set {
	struct list_head list;
	struct btf_id_set *set;
	struct module *owner;
};

struct kfunc_btf_id_list {
	struct list_head list;
	struct mutex mutex;
};

#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
			       struct kfunc_btf_id_set *s);
void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
				 struct kfunc_btf_id_set *s);
bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist, u32 kfunc_id,
			      struct module *owner);

extern struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list;
extern struct kfunc_btf_id_list prog_test_kfunc_list;
#else
static inline void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
					     struct kfunc_btf_id_set *s)
{
}
static inline void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
					       struct kfunc_btf_id_set *s)
{
}
static inline bool bpf_check_mod_kfunc_call(struct kfunc_btf_id_list *klist,
					    u32 kfunc_id, struct module *owner)
{
	return false;
}

static struct kfunc_btf_id_list bpf_tcp_ca_kfunc_list __maybe_unused;
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),     \
					 THIS_MODULE }

#endif
+0 −46
Original line number Diff line number Diff line
@@ -6682,52 +6682,6 @@ int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,
}
EXPORT_SYMBOL_GPL(register_btf_kfunc_id_set);

#ifdef CONFIG_DEBUG_INFO_BTF_MODULES

void register_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
			       struct kfunc_btf_id_set *s)
{
	mutex_lock(&l->mutex);
	list_add(&s->list, &l->list);
	mutex_unlock(&l->mutex);
}
EXPORT_SYMBOL_GPL(register_kfunc_btf_id_set);

void unregister_kfunc_btf_id_set(struct kfunc_btf_id_list *l,
				 struct kfunc_btf_id_set *s)
{
	mutex_lock(&l->mutex);
	list_del_init(&s->list);
	mutex_unlock(&l->mutex);
}
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)
{
	struct kfunc_btf_id_set *s;

	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;
		}
	}
	mutex_unlock(&klist->mutex);
	return false;
}

#define DEFINE_KFUNC_BTF_ID_LIST(name)                                         \
	struct kfunc_btf_id_list name = { LIST_HEAD_INIT(name.list),           \
					  __MUTEX_INITIALIZER(name.mutex) };   \
	EXPORT_SYMBOL_GPL(name)

DEFINE_KFUNC_BTF_ID_LIST(bpf_tcp_ca_kfunc_list);
DEFINE_KFUNC_BTF_ID_LIST(prog_test_kfunc_list);

#endif

int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
			      const struct btf *targ_btf, __u32 targ_id)
{
+8 −12
Original line number Diff line number Diff line
@@ -1741,7 +1741,7 @@ find_kfunc_desc(const struct bpf_prog *prog, u32 func_id, u16 offset)
}

static struct btf *__find_kfunc_desc_btf(struct bpf_verifier_env *env,
					 s16 offset, struct module **btf_modp)
					 s16 offset)
{
	struct bpf_kfunc_btf kf_btf = { .offset = offset };
	struct bpf_kfunc_btf_tab *tab;
@@ -1795,8 +1795,6 @@ static struct btf *__find_kfunc_desc_btf(struct bpf_verifier_env *env,
		sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
		     kfunc_btf_cmp_by_off, NULL);
	}
	if (btf_modp)
		*btf_modp = b->module;
	return b->btf;
}

@@ -1813,8 +1811,7 @@ void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab)
}

static struct btf *find_kfunc_desc_btf(struct bpf_verifier_env *env,
				       u32 func_id, s16 offset,
				       struct module **btf_modp)
				       u32 func_id, s16 offset)
{
	if (offset) {
		if (offset < 0) {
@@ -1825,7 +1822,7 @@ static struct btf *find_kfunc_desc_btf(struct bpf_verifier_env *env,
			return ERR_PTR(-EINVAL);
		}

		return __find_kfunc_desc_btf(env, offset, btf_modp);
		return __find_kfunc_desc_btf(env, offset);
	}
	return btf_vmlinux ?: ERR_PTR(-ENOENT);
}
@@ -1888,7 +1885,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
		prog_aux->kfunc_btf_tab = btf_tab;
	}

	desc_btf = find_kfunc_desc_btf(env, func_id, offset, NULL);
	desc_btf = find_kfunc_desc_btf(env, func_id, offset);
	if (IS_ERR(desc_btf)) {
		verbose(env, "failed to find BTF for kernel function\n");
		return PTR_ERR(desc_btf);
@@ -2349,7 +2346,7 @@ static const char *disasm_kfunc_name(void *data, const struct bpf_insn *insn)
	if (insn->src_reg != BPF_PSEUDO_KFUNC_CALL)
		return NULL;

	desc_btf = find_kfunc_desc_btf(data, insn->imm, insn->off, NULL);
	desc_btf = find_kfunc_desc_btf(data, insn->imm, insn->off);
	if (IS_ERR(desc_btf))
		return "<error>";

@@ -6820,7 +6817,6 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn)
	struct bpf_reg_state *regs = cur_regs(env);
	const char *func_name, *ptr_type_name;
	u32 i, nargs, func_id, ptr_type_id;
	struct module *btf_mod = NULL;
	const struct btf_param *args;
	struct btf *desc_btf;
	int err;
@@ -6829,7 +6825,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn)
	if (!insn->imm)
		return 0;

	desc_btf = find_kfunc_desc_btf(env, insn->imm, insn->off, &btf_mod);
	desc_btf = find_kfunc_desc_btf(env, insn->imm, insn->off);
	if (IS_ERR(desc_btf))
		return PTR_ERR(desc_btf);

@@ -6838,8 +6834,8 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn)
	func_name = btf_name_by_offset(desc_btf, func->name_off);
	func_proto = btf_type_by_id(desc_btf, func->type);

	if (!env->ops->check_kfunc_call ||
	    !env->ops->check_kfunc_call(func_id, btf_mod)) {
	if (!btf_kfunc_id_set_contains(desc_btf, resolve_prog_type(env->prog),
				      BTF_KFUNC_TYPE_CHECK, func_id)) {
		verbose(env, "calling kernel function %s is not allowed\n",
			func_name);
		return -EACCES;
+14 −9
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/btf.h>
#include <linux/btf_ids.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
#include <linux/etherdevice.h>
#include <linux/filter.h>
@@ -236,18 +237,11 @@ __diag_pop();

ALLOW_ERROR_INJECTION(bpf_modify_return_test, ERRNO);

BTF_SET_START(test_sk_kfunc_ids)
BTF_SET_START(test_sk_check_kfunc_ids)
BTF_ID(func, bpf_kfunc_call_test1)
BTF_ID(func, bpf_kfunc_call_test2)
BTF_ID(func, bpf_kfunc_call_test3)
BTF_SET_END(test_sk_kfunc_ids)

bool bpf_prog_test_check_kfunc_call(u32 kfunc_id, struct module *owner)
{
	if (btf_id_set_contains(&test_sk_kfunc_ids, kfunc_id))
		return true;
	return bpf_check_mod_kfunc_call(&prog_test_kfunc_list, kfunc_id, owner);
}
BTF_SET_END(test_sk_check_kfunc_ids)

static void *bpf_test_init(const union bpf_attr *kattr, u32 size,
			   u32 headroom, u32 tailroom)
@@ -1067,3 +1061,14 @@ int bpf_prog_test_run_syscall(struct bpf_prog *prog,
	kfree(ctx);
	return err;
}

static const struct btf_kfunc_id_set bpf_prog_test_kfunc_set = {
	.owner     = THIS_MODULE,
	.check_set = &test_sk_check_kfunc_ids,
};

static int __init bpf_prog_test_run_init(void)
{
	return register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &bpf_prog_test_kfunc_set);
}
late_initcall(bpf_prog_test_run_init);
Loading