-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: add CO-RE relocs testing setup
Add CO-RE relocation test runner. Add one simple test validating that libbpf's logic for searching for kernel image and loading BTF out of it works. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Song Liu <songliubraving@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Andrii Nakryiko
authored and
Alexei Starovoitov
committed
Aug 7, 2019
1 parent
2dc26d5
commit df36e62
Showing
2 changed files
with
165 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
#include <test_progs.h> | ||
|
||
struct core_reloc_test_case { | ||
const char *case_name; | ||
const char *bpf_obj_file; | ||
const char *btf_src_file; | ||
const char *input; | ||
int input_len; | ||
const char *output; | ||
int output_len; | ||
bool fails; | ||
}; | ||
|
||
static struct core_reloc_test_case test_cases[] = { | ||
/* validate we can find kernel image and use its BTF for relocs */ | ||
{ | ||
.case_name = "kernel", | ||
.bpf_obj_file = "test_core_reloc_kernel.o", | ||
.btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */ | ||
.input = "", | ||
.input_len = 0, | ||
.output = "\1", /* true */ | ||
.output_len = 1, | ||
}, | ||
}; | ||
|
||
struct data { | ||
char in[256]; | ||
char out[256]; | ||
}; | ||
|
||
void test_core_reloc(void) | ||
{ | ||
const char *probe_name = "raw_tracepoint/sys_enter"; | ||
struct bpf_object_load_attr load_attr = {}; | ||
struct core_reloc_test_case *test_case; | ||
int err, duration = 0, i, equal; | ||
struct bpf_link *link = NULL; | ||
struct bpf_map *data_map; | ||
struct bpf_program *prog; | ||
struct bpf_object *obj; | ||
const int zero = 0; | ||
struct data data; | ||
|
||
for (i = 0; i < ARRAY_SIZE(test_cases); i++) { | ||
test_case = &test_cases[i]; | ||
|
||
if (!test__start_subtest(test_case->case_name)) | ||
continue; | ||
|
||
obj = bpf_object__open(test_case->bpf_obj_file); | ||
if (CHECK(IS_ERR_OR_NULL(obj), "obj_open", | ||
"failed to open '%s': %ld\n", | ||
test_case->bpf_obj_file, PTR_ERR(obj))) | ||
continue; | ||
|
||
prog = bpf_object__find_program_by_title(obj, probe_name); | ||
if (CHECK(!prog, "find_probe", | ||
"prog '%s' not found\n", probe_name)) | ||
goto cleanup; | ||
bpf_program__set_type(prog, BPF_PROG_TYPE_RAW_TRACEPOINT); | ||
|
||
load_attr.obj = obj; | ||
load_attr.log_level = 0; | ||
load_attr.target_btf_path = test_case->btf_src_file; | ||
err = bpf_object__load_xattr(&load_attr); | ||
if (test_case->fails) { | ||
CHECK(!err, "obj_load_fail", | ||
"should fail to load prog '%s'\n", probe_name); | ||
goto cleanup; | ||
} else { | ||
if (CHECK(err, "obj_load", | ||
"failed to load prog '%s': %d\n", | ||
probe_name, err)) | ||
goto cleanup; | ||
} | ||
|
||
link = bpf_program__attach_raw_tracepoint(prog, "sys_enter"); | ||
if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", | ||
PTR_ERR(link))) | ||
goto cleanup; | ||
|
||
data_map = bpf_object__find_map_by_name(obj, "test_cor.bss"); | ||
if (CHECK(!data_map, "find_data_map", "data map not found\n")) | ||
goto cleanup; | ||
|
||
memset(&data, 0, sizeof(data)); | ||
memcpy(data.in, test_case->input, test_case->input_len); | ||
|
||
err = bpf_map_update_elem(bpf_map__fd(data_map), | ||
&zero, &data, 0); | ||
if (CHECK(err, "update_data_map", | ||
"failed to update .data map: %d\n", err)) | ||
goto cleanup; | ||
|
||
/* trigger test run */ | ||
usleep(1); | ||
|
||
err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, &data); | ||
if (CHECK(err, "get_result", | ||
"failed to get output data: %d\n", err)) | ||
goto cleanup; | ||
|
||
equal = memcmp(data.out, test_case->output, | ||
test_case->output_len) == 0; | ||
if (CHECK(!equal, "check_result", | ||
"input/output data don't match\n")) { | ||
int j; | ||
|
||
for (j = 0; j < test_case->input_len; j++) { | ||
printf("input byte #%d: 0x%02hhx\n", | ||
j, test_case->input[j]); | ||
} | ||
for (j = 0; j < test_case->output_len; j++) { | ||
printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n", | ||
j, test_case->output[j], data.out[j]); | ||
} | ||
goto cleanup; | ||
} | ||
|
||
cleanup: | ||
if (!IS_ERR_OR_NULL(link)) { | ||
bpf_link__destroy(link); | ||
link = NULL; | ||
} | ||
bpf_object__close(obj); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
// Copyright (c) 2019 Facebook | ||
|
||
#include <linux/bpf.h> | ||
#include <stdint.h> | ||
#include "bpf_helpers.h" | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
static volatile struct data { | ||
char in[256]; | ||
char out[256]; | ||
} data; | ||
|
||
struct task_struct { | ||
int pid; | ||
int tgid; | ||
}; | ||
|
||
SEC("raw_tracepoint/sys_enter") | ||
int test_core_kernel(void *ctx) | ||
{ | ||
struct task_struct *task = (void *)bpf_get_current_task(); | ||
uint64_t pid_tgid = bpf_get_current_pid_tgid(); | ||
int pid, tgid; | ||
|
||
if (BPF_CORE_READ(&pid, &task->pid) || | ||
BPF_CORE_READ(&tgid, &task->tgid)) | ||
return 1; | ||
|
||
/* validate pid + tgid matches */ | ||
data.out[0] = (((uint64_t)pid << 32) | tgid) == pid_tgid; | ||
|
||
return 0; | ||
} | ||
|