Skip to content

Commit 7c7a80e

Browse files
author
Alexei Starovoitov
committed
Merge branch 'Support kernel module ksym variables'
Andrii Nakryiko says: ==================== Add support for using kernel module global variables (__ksym externs in BPF program). BPF verifier will now support ldimm64 with src_reg=BPF_PSEUDO_BTF_ID and non-zero insn[1].imm field, specifying module BTF's FD. In such case, module BTF object, similarly to BPF maps referenced from ldimm64 with src_reg=BPF_PSEUDO_MAP_FD, will be recorded in bpf_progran's auxiliary data and refcnt will be increased for both BTF object itself and its kernel module. This makes sure kernel module won't be unloaded from under active attached BPF program. These refcounts will be dropped when BPF program is unloaded. New selftest validates all this is working as intended. bpf_testmod.ko is extended with per-CPU variable. Selftests expects the latest pahole changes (soon to be released as v1.20) to generate per-CPU variable BTF info for kernel module. v2->v3: - added comments, addressed feedack (Yonghong, Hao); v1->v2: - fixed few compiler warnings, posted as separate pre-patches; rfc->v1: - use sys_membarrier(MEMBARRIER_CMD_GLOBAL) (Alexei). Cc: Hao Luo <haoluo@google.com> ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents 3218231 + 430d97a commit 7c7a80e

File tree

14 files changed

+305
-84
lines changed

14 files changed

+305
-84
lines changed

include/linux/bpf.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,9 +761,15 @@ struct bpf_ctx_arg_aux {
761761
u32 btf_id;
762762
};
763763

764+
struct btf_mod_pair {
765+
struct btf *btf;
766+
struct module *module;
767+
};
768+
764769
struct bpf_prog_aux {
765770
atomic64_t refcnt;
766771
u32 used_map_cnt;
772+
u32 used_btf_cnt;
767773
u32 max_ctx_offset;
768774
u32 max_pkt_offset;
769775
u32 max_tp_access;
@@ -802,6 +808,7 @@ struct bpf_prog_aux {
802808
const struct bpf_prog_ops *ops;
803809
struct bpf_map **used_maps;
804810
struct mutex used_maps_mutex; /* mutex for used_maps and used_map_cnt */
811+
struct btf_mod_pair *used_btfs;
805812
struct bpf_prog *prog;
806813
struct user_struct *user;
807814
u64 load_time; /* ns since boottime */
@@ -1206,8 +1213,6 @@ void bpf_prog_sub(struct bpf_prog *prog, int i);
12061213
void bpf_prog_inc(struct bpf_prog *prog);
12071214
struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
12081215
void bpf_prog_put(struct bpf_prog *prog);
1209-
void __bpf_free_used_maps(struct bpf_prog_aux *aux,
1210-
struct bpf_map **used_maps, u32 len);
12111216

12121217
void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
12131218
void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
@@ -1403,7 +1408,10 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size)
14031408
/* verify correctness of eBPF program */
14041409
int bpf_check(struct bpf_prog **fp, union bpf_attr *attr,
14051410
union bpf_attr __user *uattr);
1411+
1412+
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
14061413
void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
1414+
#endif
14071415

14081416
struct btf *bpf_get_btf_vmlinux(void);
14091417

@@ -1667,12 +1675,18 @@ bpf_base_func_proto(enum bpf_func_id func_id)
16671675
}
16681676
#endif /* CONFIG_BPF_SYSCALL */
16691677

1678+
void __bpf_free_used_btfs(struct bpf_prog_aux *aux,
1679+
struct btf_mod_pair *used_btfs, u32 len);
1680+
16701681
static inline struct bpf_prog *bpf_prog_get_type(u32 ufd,
16711682
enum bpf_prog_type type)
16721683
{
16731684
return bpf_prog_get_type_dev(ufd, type, false);
16741685
}
16751686

1687+
void __bpf_free_used_maps(struct bpf_prog_aux *aux,
1688+
struct bpf_map **used_maps, u32 len);
1689+
16761690
bool bpf_prog_get_ok(struct bpf_prog *, enum bpf_prog_type *, bool);
16771691

16781692
int bpf_prog_offload_compile(struct bpf_prog *prog);

include/linux/bpf_verifier.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ struct bpf_insn_aux_data {
340340
};
341341

342342
#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
343+
#define MAX_USED_BTFS 64 /* max number of BTFs accessed by one BPF program */
343344

344345
#define BPF_VERIFIER_TMP_LOG_SIZE 1024
345346

@@ -398,7 +399,9 @@ struct bpf_verifier_env {
398399
struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
399400
struct bpf_verifier_state_list *free_list;
400401
struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */
402+
struct btf_mod_pair used_btfs[MAX_USED_BTFS]; /* array of BTF's used by BPF program */
401403
u32 used_map_cnt; /* number of used maps */
404+
u32 used_btf_cnt; /* number of used BTF objects */
402405
u32 id_gen; /* used to generate unique reg IDs */
403406
bool allow_ptr_leaks;
404407
bool allow_ptr_to_map_access;

include/linux/btf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ int btf_type_snprintf_show(const struct btf *btf, u32 type_id, void *obj,
9191
int btf_get_fd_by_id(u32 id);
9292
u32 btf_obj_id(const struct btf *btf);
9393
bool btf_is_kernel(const struct btf *btf);
94+
bool btf_is_module(const struct btf *btf);
95+
struct module *btf_try_get_module(const struct btf *btf);
96+
u32 btf_nr_types(const struct btf *btf);
9497
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
9598
const struct btf_member *m,
9699
u32 expected_offset, u32 expected_size);

include/linux/filter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp);
886886
u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
887887
#define __bpf_call_base_args \
888888
((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \
889-
__bpf_call_base)
889+
(void *)__bpf_call_base)
890890

891891
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog);
892892
void bpf_jit_compile(struct bpf_prog *prog);

kernel/bpf/btf.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ static bool btf_type_is_datasec(const struct btf_type *t)
458458
return BTF_INFO_KIND(t->info) == BTF_KIND_DATASEC;
459459
}
460460

461-
static u32 btf_nr_types_total(const struct btf *btf)
461+
u32 btf_nr_types(const struct btf *btf)
462462
{
463463
u32 total = 0;
464464

@@ -476,7 +476,7 @@ s32 btf_find_by_name_kind(const struct btf *btf, const char *name, u8 kind)
476476
const char *tname;
477477
u32 i, total;
478478

479-
total = btf_nr_types_total(btf);
479+
total = btf_nr_types(btf);
480480
for (i = 1; i < total; i++) {
481481
t = btf_type_by_id(btf, i);
482482
if (BTF_INFO_KIND(t->info) != kind)
@@ -5743,6 +5743,11 @@ bool btf_is_kernel(const struct btf *btf)
57435743
return btf->kernel_btf;
57445744
}
57455745

5746+
bool btf_is_module(const struct btf *btf)
5747+
{
5748+
return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0;
5749+
}
5750+
57465751
static int btf_id_cmp_func(const void *a, const void *b)
57475752
{
57485753
const int *pa = a, *pb = b;
@@ -5877,3 +5882,25 @@ static int __init btf_module_init(void)
58775882

58785883
fs_initcall(btf_module_init);
58795884
#endif /* CONFIG_DEBUG_INFO_BTF_MODULES */
5885+
5886+
struct module *btf_try_get_module(const struct btf *btf)
5887+
{
5888+
struct module *res = NULL;
5889+
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
5890+
struct btf_module *btf_mod, *tmp;
5891+
5892+
mutex_lock(&btf_module_mutex);
5893+
list_for_each_entry_safe(btf_mod, tmp, &btf_modules, list) {
5894+
if (btf_mod->btf != btf)
5895+
continue;
5896+
5897+
if (try_module_get(btf_mod->module))
5898+
res = btf_mod->module;
5899+
5900+
break;
5901+
}
5902+
mutex_unlock(&btf_module_mutex);
5903+
#endif
5904+
5905+
return res;
5906+
}

kernel/bpf/core.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,13 +2119,36 @@ static void bpf_free_used_maps(struct bpf_prog_aux *aux)
21192119
kfree(aux->used_maps);
21202120
}
21212121

2122+
void __bpf_free_used_btfs(struct bpf_prog_aux *aux,
2123+
struct btf_mod_pair *used_btfs, u32 len)
2124+
{
2125+
#ifdef CONFIG_BPF_SYSCALL
2126+
struct btf_mod_pair *btf_mod;
2127+
u32 i;
2128+
2129+
for (i = 0; i < len; i++) {
2130+
btf_mod = &used_btfs[i];
2131+
if (btf_mod->module)
2132+
module_put(btf_mod->module);
2133+
btf_put(btf_mod->btf);
2134+
}
2135+
#endif
2136+
}
2137+
2138+
static void bpf_free_used_btfs(struct bpf_prog_aux *aux)
2139+
{
2140+
__bpf_free_used_btfs(aux, aux->used_btfs, aux->used_btf_cnt);
2141+
kfree(aux->used_btfs);
2142+
}
2143+
21222144
static void bpf_prog_free_deferred(struct work_struct *work)
21232145
{
21242146
struct bpf_prog_aux *aux;
21252147
int i;
21262148

21272149
aux = container_of(work, struct bpf_prog_aux, work);
21282150
bpf_free_used_maps(aux);
2151+
bpf_free_used_btfs(aux);
21292152
if (bpf_prog_is_dev_bound(aux))
21302153
bpf_prog_offload_destroy(aux->prog);
21312154
#ifdef CONFIG_PERF_EVENTS

0 commit comments

Comments
 (0)