Skip to content

Commit a1a771b

Browse files
theihorAlexei Starovoitov
authored andcommitted
selftests/bpf: Refactor bpf_get_ksyms() trace helper
ASAN reported a memory leak in bpf_get_ksyms(): it allocates a struct ksyms internally and never frees it. Move struct ksyms to trace_helpers.h and return it from the bpf_get_ksyms(), giving ownership to the caller. Add filtered_syms and filtered_cnt fields to the ksyms to hold the filtered array of symbols, previously returned by bpf_get_ksyms(). Fixup the call sites: kprobe_multi_test and bench_trigger. Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20260223190736.649171-10-ihor.solodrai@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 45897ce commit a1a771b

4 files changed

Lines changed: 34 additions & 26 deletions

File tree

tools/testing/selftests/bpf/benchs/bench_trigger.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ static void trigger_fentry_setup(void)
230230
static void attach_ksyms_all(struct bpf_program *empty, bool kretprobe)
231231
{
232232
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
233-
char **syms = NULL;
234-
size_t cnt = 0;
233+
struct bpf_link *link = NULL;
234+
struct ksyms *ksyms = NULL;
235235

236236
/* Some recursive functions will be skipped in
237237
* bpf_get_ksyms -> skip_entry, as they can introduce sufficient
@@ -241,16 +241,18 @@ static void attach_ksyms_all(struct bpf_program *empty, bool kretprobe)
241241
* So, don't run the kprobe-multi-all and kretprobe-multi-all on
242242
* a debug kernel.
243243
*/
244-
if (bpf_get_ksyms(&syms, &cnt, true)) {
244+
if (bpf_get_ksyms(&ksyms, true)) {
245245
fprintf(stderr, "failed to get ksyms\n");
246246
exit(1);
247247
}
248248

249-
opts.syms = (const char **) syms;
250-
opts.cnt = cnt;
249+
opts.syms = (const char **)ksyms->filtered_syms;
250+
opts.cnt = ksyms->filtered_cnt;
251251
opts.retprobe = kretprobe;
252252
/* attach empty to all the kernel functions except bpf_get_numa_node_id. */
253-
if (!bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts)) {
253+
link = bpf_program__attach_kprobe_multi_opts(empty, NULL, &opts);
254+
free_kallsyms_local(ksyms);
255+
if (!link) {
254256
fprintf(stderr, "failed to attach bpf_program__attach_kprobe_multi_opts to all\n");
255257
exit(1);
256258
}

tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -456,25 +456,23 @@ static void test_kprobe_multi_bench_attach(bool kernel)
456456
{
457457
LIBBPF_OPTS(bpf_kprobe_multi_opts, opts);
458458
struct kprobe_multi_empty *skel = NULL;
459-
char **syms = NULL;
460-
size_t cnt = 0;
459+
struct ksyms *ksyms = NULL;
461460

462-
if (!ASSERT_OK(bpf_get_ksyms(&syms, &cnt, kernel), "bpf_get_ksyms"))
461+
if (!ASSERT_OK(bpf_get_ksyms(&ksyms, kernel), "bpf_get_ksyms"))
463462
return;
464463

465464
skel = kprobe_multi_empty__open_and_load();
466465
if (!ASSERT_OK_PTR(skel, "kprobe_multi_empty__open_and_load"))
467466
goto cleanup;
468467

469-
opts.syms = (const char **) syms;
470-
opts.cnt = cnt;
468+
opts.syms = (const char **)ksyms->filtered_syms;
469+
opts.cnt = ksyms->filtered_cnt;
471470

472471
do_bench_test(skel, &opts);
473472

474473
cleanup:
475474
kprobe_multi_empty__destroy(skel);
476-
if (syms)
477-
free(syms);
475+
free_kallsyms_local(ksyms);
478476
}
479477

480478
static void test_kprobe_multi_bench_attach_addr(bool kernel)

tools/testing/selftests/bpf/trace_helpers.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,6 @@
2424
#define TRACEFS_PIPE "/sys/kernel/tracing/trace_pipe"
2525
#define DEBUGFS_PIPE "/sys/kernel/debug/tracing/trace_pipe"
2626

27-
struct ksyms {
28-
struct ksym *syms;
29-
size_t sym_cap;
30-
size_t sym_cnt;
31-
};
32-
3327
static struct ksyms *ksyms;
3428
static pthread_mutex_t ksyms_mutex = PTHREAD_MUTEX_INITIALIZER;
3529

@@ -54,6 +48,8 @@ void free_kallsyms_local(struct ksyms *ksyms)
5448
if (!ksyms)
5549
return;
5650

51+
free(ksyms->filtered_syms);
52+
5753
if (!ksyms->syms) {
5854
free(ksyms);
5955
return;
@@ -610,7 +606,7 @@ static int search_kallsyms_compare(const void *p1, const struct ksym *p2)
610606
return compare_name(p1, p2->name);
611607
}
612608

613-
int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
609+
int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel)
614610
{
615611
size_t cap = 0, cnt = 0;
616612
char *name = NULL, *ksym_name, **syms = NULL;
@@ -637,8 +633,10 @@ int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
637633
else
638634
f = fopen("/sys/kernel/debug/tracing/available_filter_functions", "r");
639635

640-
if (!f)
636+
if (!f) {
637+
free_kallsyms_local(ksyms);
641638
return -EINVAL;
639+
}
642640

643641
map = hashmap__new(symbol_hash, symbol_equal, NULL);
644642
if (IS_ERR(map)) {
@@ -679,15 +677,18 @@ int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel)
679677
syms[cnt++] = ksym_name;
680678
}
681679

682-
*symsp = syms;
683-
*cntp = cnt;
680+
ksyms->filtered_syms = syms;
681+
ksyms->filtered_cnt = cnt;
682+
*ksymsp = ksyms;
684683

685684
error:
686685
free(name);
687686
fclose(f);
688687
hashmap__free(map);
689-
if (err)
688+
if (err) {
690689
free(syms);
690+
free_kallsyms_local(ksyms);
691+
}
691692
return err;
692693
}
693694

tools/testing/selftests/bpf/trace_helpers.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ struct ksym {
2323
long addr;
2424
char *name;
2525
};
26-
struct ksyms;
26+
27+
struct ksyms {
28+
struct ksym *syms;
29+
size_t sym_cap;
30+
size_t sym_cnt;
31+
char **filtered_syms;
32+
size_t filtered_cnt;
33+
};
2734

2835
typedef int (*ksym_cmp_t)(const void *p1, const void *p2);
2936
typedef int (*ksym_search_cmp_t)(const void *p1, const struct ksym *p2);
@@ -53,7 +60,7 @@ ssize_t get_rel_offset(uintptr_t addr);
5360

5461
int read_build_id(const char *path, char *build_id, size_t size);
5562

56-
int bpf_get_ksyms(char ***symsp, size_t *cntp, bool kernel);
63+
int bpf_get_ksyms(struct ksyms **ksymsp, bool kernel);
5764
int bpf_get_addrs(unsigned long **addrsp, size_t *cntp, bool kernel);
5865

5966
#endif

0 commit comments

Comments
 (0)