Commit 2357672c authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov

bpf: Introduce BPF support for kernel module function calls

This change adds support on the kernel side to allow for BPF programs to
call kernel module functions. Userspace will prepare an array of module
BTF fds that is passed in during BPF_PROG_LOAD using fd_array parameter.
In the kernel, the module BTFs are placed in the auxilliary struct for
bpf_prog, and loaded as needed.

The verifier then uses insn->off to index into the fd_array. insn->off
0 is reserved for vmlinux BTF (for backwards compat), so userspace must
use an fd_array index > 0 for module kfunc support. kfunc_btf_tab is
sorted based on offset in an array, and each offset corresponds to one
descriptor, with a max limit up to 256 such module BTFs.

We also change existing kfunc_tab to distinguish each element based on
imm, off pair as each such call will now be distinct.

Another change is to check_kfunc_call callback, which now include a
struct module * pointer, this is to be used in later patch such that the
kfunc_id and module pointer are matched for dynamically registered BTF
sets from loadable modules, so that same kfunc_id in two modules doesn't
lead to check_kfunc_call succeeding. For the duration of the
check_kfunc_call, the reference to struct module exists, as it returns
the pointer stored in kfunc_btf_tab.
Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211002011757.311265-2-memxor@gmail.com
parent d0f1c248
...@@ -513,7 +513,7 @@ struct bpf_verifier_ops { ...@@ -513,7 +513,7 @@ struct bpf_verifier_ops {
const struct btf_type *t, int off, int size, const struct btf_type *t, int off, int size,
enum bpf_access_type atype, enum bpf_access_type atype,
u32 *next_btf_id); u32 *next_btf_id);
bool (*check_kfunc_call)(u32 kfunc_btf_id); bool (*check_kfunc_call)(u32 kfunc_btf_id, struct module *owner);
}; };
struct bpf_prog_offload_ops { struct bpf_prog_offload_ops {
...@@ -877,6 +877,7 @@ struct bpf_prog_aux { ...@@ -877,6 +877,7 @@ struct bpf_prog_aux {
void *jit_data; /* JIT specific data. arch dependent */ void *jit_data; /* JIT specific data. arch dependent */
struct bpf_jit_poke_descriptor *poke_tab; struct bpf_jit_poke_descriptor *poke_tab;
struct bpf_kfunc_desc_tab *kfunc_tab; struct bpf_kfunc_desc_tab *kfunc_tab;
struct bpf_kfunc_btf_tab *kfunc_btf_tab;
u32 size_poke_tab; u32 size_poke_tab;
struct bpf_ksym ksym; struct bpf_ksym ksym;
const struct bpf_prog_ops *ops; const struct bpf_prog_ops *ops;
...@@ -1639,7 +1640,7 @@ int bpf_prog_test_run_raw_tp(struct bpf_prog *prog, ...@@ -1639,7 +1640,7 @@ int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
const union bpf_attr *kattr, const union bpf_attr *kattr,
union bpf_attr __user *uattr); union bpf_attr __user *uattr);
bool bpf_prog_test_check_kfunc_call(u32 kfunc_id); 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, bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const struct bpf_prog *prog, const struct bpf_prog *prog,
struct bpf_insn_access_aux *info); struct bpf_insn_access_aux *info);
...@@ -1860,7 +1861,8 @@ static inline int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, ...@@ -1860,7 +1861,8 @@ static inline int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog,
return -ENOTSUPP; return -ENOTSUPP;
} }
static inline bool bpf_prog_test_check_kfunc_call(u32 kfunc_id) static inline bool bpf_prog_test_check_kfunc_call(u32 kfunc_id,
struct module *owner)
{ {
return false; return false;
} }
......
...@@ -527,5 +527,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log, ...@@ -527,5 +527,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
const struct bpf_prog *tgt_prog, const struct bpf_prog *tgt_prog,
u32 btf_id, u32 btf_id,
struct bpf_attach_target_info *tgt_info); struct bpf_attach_target_info *tgt_info);
void bpf_free_kfunc_btf_tab(struct bpf_kfunc_btf_tab *tab);
#endif /* _LINUX_BPF_VERIFIER_H */ #endif /* _LINUX_BPF_VERIFIER_H */
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/extable.h> #include <linux/extable.h>
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/bpf_verifier.h>
#include <asm/barrier.h> #include <asm/barrier.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -2255,6 +2256,9 @@ static void bpf_prog_free_deferred(struct work_struct *work) ...@@ -2255,6 +2256,9 @@ static void bpf_prog_free_deferred(struct work_struct *work)
int i; int i;
aux = container_of(work, struct bpf_prog_aux, work); aux = container_of(work, struct bpf_prog_aux, work);
#ifdef CONFIG_BPF_SYSCALL
bpf_free_kfunc_btf_tab(aux->kfunc_btf_tab);
#endif
bpf_free_used_maps(aux); bpf_free_used_maps(aux);
bpf_free_used_btfs(aux); bpf_free_used_btfs(aux);
if (bpf_prog_is_dev_bound(aux)) if (bpf_prog_is_dev_bound(aux))
......
This diff is collapsed.
...@@ -241,7 +241,7 @@ BTF_ID(func, bpf_kfunc_call_test2) ...@@ -241,7 +241,7 @@ BTF_ID(func, bpf_kfunc_call_test2)
BTF_ID(func, bpf_kfunc_call_test3) BTF_ID(func, bpf_kfunc_call_test3)
BTF_SET_END(test_sk_kfunc_ids) BTF_SET_END(test_sk_kfunc_ids)
bool bpf_prog_test_check_kfunc_call(u32 kfunc_id) bool bpf_prog_test_check_kfunc_call(u32 kfunc_id, struct module *owner)
{ {
return btf_id_set_contains(&test_sk_kfunc_ids, kfunc_id); return btf_id_set_contains(&test_sk_kfunc_ids, kfunc_id);
} }
......
...@@ -255,7 +255,7 @@ BTF_ID(func, bbr_set_state) ...@@ -255,7 +255,7 @@ BTF_ID(func, bbr_set_state)
#endif /* CONFIG_X86 */ #endif /* CONFIG_X86 */
BTF_SET_END(bpf_tcp_ca_kfunc_ids) BTF_SET_END(bpf_tcp_ca_kfunc_ids)
static bool bpf_tcp_ca_check_kfunc_call(u32 kfunc_btf_id) static bool bpf_tcp_ca_check_kfunc_call(u32 kfunc_btf_id, struct module *owner)
{ {
return btf_id_set_contains(&bpf_tcp_ca_kfunc_ids, kfunc_btf_id); return btf_id_set_contains(&bpf_tcp_ca_kfunc_ids, kfunc_btf_id);
} }
......
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