Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Ksyms_btf to test typed ksyms

Selftests for typed ksyms. Tests two types of ksyms: one is a struct,
the other is a plain int. This tests two paths in the kernel. Struct
ksyms will be converted into PTR_TO_BTF_ID by the verifier while int
typed ksyms will be converted into PTR_TO_MEM.

Signed-off-by: Hao Luo <haoluo@google.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200929235049.2533242-4-haoluo@google.com

authored by

Hao Luo and committed by
Alexei Starovoitov
2c2f6abe d370bbe1

+137 -25
+13 -25
tools/testing/selftests/bpf/prog_tests/ksyms.c
··· 7 7 8 8 static int duration; 9 9 10 - static __u64 kallsyms_find(const char *sym) 11 - { 12 - char type, name[500]; 13 - __u64 addr, res = 0; 14 - FILE *f; 15 - 16 - f = fopen("/proc/kallsyms", "r"); 17 - if (CHECK(!f, "kallsyms_fopen", "failed to open: %d\n", errno)) 18 - return 0; 19 - 20 - while (fscanf(f, "%llx %c %499s%*[^\n]\n", &addr, &type, name) > 0) { 21 - if (strcmp(name, sym) == 0) { 22 - res = addr; 23 - goto out; 24 - } 25 - } 26 - 27 - CHECK(false, "not_found", "symbol %s not found\n", sym); 28 - out: 29 - fclose(f); 30 - return res; 31 - } 32 - 33 10 void test_ksyms(void) 34 11 { 35 - __u64 per_cpu_start_addr = kallsyms_find("__per_cpu_start"); 36 - __u64 link_fops_addr = kallsyms_find("bpf_link_fops"); 37 12 const char *btf_path = "/sys/kernel/btf/vmlinux"; 38 13 struct test_ksyms *skel; 39 14 struct test_ksyms__data *data; 15 + __u64 link_fops_addr, per_cpu_start_addr; 40 16 struct stat st; 41 17 __u64 btf_size; 42 18 int err; 19 + 20 + err = kallsyms_find("bpf_link_fops", &link_fops_addr); 21 + if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno)) 22 + return; 23 + if (CHECK(err == -ENOENT, "ksym_find", "symbol 'bpf_link_fops' not found\n")) 24 + return; 25 + 26 + err = kallsyms_find("__per_cpu_start", &per_cpu_start_addr); 27 + if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno)) 28 + return; 29 + if (CHECK(err == -ENOENT, "ksym_find", "symbol 'per_cpu_start' not found\n")) 30 + return; 43 31 44 32 if (CHECK(stat(btf_path, &st), "stat_btf", "err %d\n", errno)) 45 33 return;
+70
tools/testing/selftests/bpf/prog_tests/ksyms_btf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Google */ 3 + 4 + #include <test_progs.h> 5 + #include <bpf/libbpf.h> 6 + #include <bpf/btf.h> 7 + #include "test_ksyms_btf.skel.h" 8 + 9 + static int duration; 10 + 11 + void test_ksyms_btf(void) 12 + { 13 + __u64 runqueues_addr, bpf_prog_active_addr; 14 + struct test_ksyms_btf *skel = NULL; 15 + struct test_ksyms_btf__data *data; 16 + struct btf *btf; 17 + int percpu_datasec; 18 + int err; 19 + 20 + err = kallsyms_find("runqueues", &runqueues_addr); 21 + if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno)) 22 + return; 23 + if (CHECK(err == -ENOENT, "ksym_find", "symbol 'runqueues' not found\n")) 24 + return; 25 + 26 + err = kallsyms_find("bpf_prog_active", &bpf_prog_active_addr); 27 + if (CHECK(err == -EINVAL, "kallsyms_fopen", "failed to open: %d\n", errno)) 28 + return; 29 + if (CHECK(err == -ENOENT, "ksym_find", "symbol 'bpf_prog_active' not found\n")) 30 + return; 31 + 32 + btf = libbpf_find_kernel_btf(); 33 + if (CHECK(IS_ERR(btf), "btf_exists", "failed to load kernel BTF: %ld\n", 34 + PTR_ERR(btf))) 35 + return; 36 + 37 + percpu_datasec = btf__find_by_name_kind(btf, ".data..percpu", 38 + BTF_KIND_DATASEC); 39 + if (percpu_datasec < 0) { 40 + printf("%s:SKIP:no PERCPU DATASEC in kernel btf\n", 41 + __func__); 42 + test__skip(); 43 + goto cleanup; 44 + } 45 + 46 + skel = test_ksyms_btf__open_and_load(); 47 + if (CHECK(!skel, "skel_open", "failed to open and load skeleton\n")) 48 + goto cleanup; 49 + 50 + err = test_ksyms_btf__attach(skel); 51 + if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err)) 52 + goto cleanup; 53 + 54 + /* trigger tracepoint */ 55 + usleep(1); 56 + 57 + data = skel->data; 58 + CHECK(data->out__runqueues_addr != runqueues_addr, "runqueues_addr", 59 + "got %llu, exp %llu\n", 60 + (unsigned long long)data->out__runqueues_addr, 61 + (unsigned long long)runqueues_addr); 62 + CHECK(data->out__bpf_prog_active_addr != bpf_prog_active_addr, "bpf_prog_active_addr", 63 + "got %llu, exp %llu\n", 64 + (unsigned long long)data->out__bpf_prog_active_addr, 65 + (unsigned long long)bpf_prog_active_addr); 66 + 67 + cleanup: 68 + btf__free(btf); 69 + test_ksyms_btf__destroy(skel); 70 + }
+23
tools/testing/selftests/bpf/progs/test_ksyms_btf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Google */ 3 + 4 + #include "vmlinux.h" 5 + 6 + #include <bpf/bpf_helpers.h> 7 + 8 + __u64 out__runqueues_addr = -1; 9 + __u64 out__bpf_prog_active_addr = -1; 10 + 11 + extern const struct rq runqueues __ksym; /* struct type global var. */ 12 + extern const int bpf_prog_active __ksym; /* int type global var. */ 13 + 14 + SEC("raw_tp/sys_enter") 15 + int handler(const void *ctx) 16 + { 17 + out__runqueues_addr = (__u64)&runqueues; 18 + out__bpf_prog_active_addr = (__u64)&bpf_prog_active; 19 + 20 + return 0; 21 + } 22 + 23 + char _license[] SEC("license") = "GPL";
+27
tools/testing/selftests/bpf/trace_helpers.c
··· 90 90 return 0; 91 91 } 92 92 93 + /* open kallsyms and read symbol addresses on the fly. Without caching all symbols, 94 + * this is faster than load + find. 95 + */ 96 + int kallsyms_find(const char *sym, unsigned long long *addr) 97 + { 98 + char type, name[500]; 99 + unsigned long long value; 100 + int err = 0; 101 + FILE *f; 102 + 103 + f = fopen("/proc/kallsyms", "r"); 104 + if (!f) 105 + return -EINVAL; 106 + 107 + while (fscanf(f, "%llx %c %499s%*[^\n]\n", &value, &type, name) > 0) { 108 + if (strcmp(name, sym) == 0) { 109 + *addr = value; 110 + goto out; 111 + } 112 + } 113 + err = -ENOENT; 114 + 115 + out: 116 + fclose(f); 117 + return err; 118 + } 119 + 93 120 void read_trace_pipe(void) 94 121 { 95 122 int trace_fd;
+4
tools/testing/selftests/bpf/trace_helpers.h
··· 12 12 int load_kallsyms(void); 13 13 struct ksym *ksym_search(long key); 14 14 long ksym_get_addr(const char *name); 15 + 16 + /* open kallsyms and find addresses on the fly, faster than load + search. */ 17 + int kallsyms_find(const char *sym, unsigned long long *addr); 18 + 15 19 void read_trace_pipe(void); 16 20 17 21 #endif