-
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.
bpf/selftests: Test fentry attachment to shadowed functions
Adds a new test that tries to attach a program to fentry of two functions of the same name, one located in vmlinux and the other in bpf_testmod. To avoid conflicts with existing tests, a new function "bpf_fentry_shadow_test" was created both in vmlinux and in bpf_testmod. The previous commit fixed a bug which caused this test to fail. The verifier would always use the vmlinux function's address as the target trampoline address, hence trying to create two trampolines for a single address, which is forbidden. The test (similarly to other fentry/fexit tests) is not working on arm64 at the moment. Signed-off-by: Viktor Malik <vmalik@redhat.com> Acked-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/r/5fe2f364190b6f79b085066ed7c5989c5bc475fa.1678432753.git.vmalik@redhat.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Viktor Malik
authored and
Alexei Starovoitov
committed
Mar 16, 2023
1 parent
31bf1db
commit aa3d65d
Showing
4 changed files
with
140 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
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
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
128 changes: 128 additions & 0 deletions
128
tools/testing/selftests/bpf/prog_tests/module_fentry_shadow.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,128 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (c) 2022 Red Hat */ | ||
#include <test_progs.h> | ||
#include <bpf/btf.h> | ||
#include "bpf/libbpf_internal.h" | ||
#include "cgroup_helpers.h" | ||
|
||
static const char *module_name = "bpf_testmod"; | ||
static const char *symbol_name = "bpf_fentry_shadow_test"; | ||
|
||
static int get_bpf_testmod_btf_fd(void) | ||
{ | ||
struct bpf_btf_info info; | ||
char name[64]; | ||
__u32 id = 0, len; | ||
int err, fd; | ||
|
||
while (true) { | ||
err = bpf_btf_get_next_id(id, &id); | ||
if (err) { | ||
log_err("failed to iterate BTF objects"); | ||
return err; | ||
} | ||
|
||
fd = bpf_btf_get_fd_by_id(id); | ||
if (fd < 0) { | ||
if (errno == ENOENT) | ||
continue; /* expected race: BTF was unloaded */ | ||
err = -errno; | ||
log_err("failed to get FD for BTF object #%d", id); | ||
return err; | ||
} | ||
|
||
len = sizeof(info); | ||
memset(&info, 0, sizeof(info)); | ||
info.name = ptr_to_u64(name); | ||
info.name_len = sizeof(name); | ||
|
||
err = bpf_obj_get_info_by_fd(fd, &info, &len); | ||
if (err) { | ||
err = -errno; | ||
log_err("failed to get info for BTF object #%d", id); | ||
close(fd); | ||
return err; | ||
} | ||
|
||
if (strcmp(name, module_name) == 0) | ||
return fd; | ||
|
||
close(fd); | ||
} | ||
return -ENOENT; | ||
} | ||
|
||
void test_module_fentry_shadow(void) | ||
{ | ||
struct btf *vmlinux_btf = NULL, *mod_btf = NULL; | ||
int err, i; | ||
int btf_fd[2] = {}; | ||
int prog_fd[2] = {}; | ||
int link_fd[2] = {}; | ||
__s32 btf_id[2] = {}; | ||
|
||
LIBBPF_OPTS(bpf_prog_load_opts, load_opts, | ||
.expected_attach_type = BPF_TRACE_FENTRY, | ||
); | ||
|
||
const struct bpf_insn trace_program[] = { | ||
BPF_MOV64_IMM(BPF_REG_0, 0), | ||
BPF_EXIT_INSN(), | ||
}; | ||
|
||
vmlinux_btf = btf__load_vmlinux_btf(); | ||
if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux_btf")) | ||
return; | ||
|
||
btf_fd[1] = get_bpf_testmod_btf_fd(); | ||
if (!ASSERT_GE(btf_fd[1], 0, "get_bpf_testmod_btf_fd")) | ||
goto out; | ||
|
||
mod_btf = btf_get_from_fd(btf_fd[1], vmlinux_btf); | ||
if (!ASSERT_OK_PTR(mod_btf, "btf_get_from_fd")) | ||
goto out; | ||
|
||
btf_id[0] = btf__find_by_name_kind(vmlinux_btf, symbol_name, BTF_KIND_FUNC); | ||
if (!ASSERT_GT(btf_id[0], 0, "btf_find_by_name")) | ||
goto out; | ||
|
||
btf_id[1] = btf__find_by_name_kind(mod_btf, symbol_name, BTF_KIND_FUNC); | ||
if (!ASSERT_GT(btf_id[1], 0, "btf_find_by_name")) | ||
goto out; | ||
|
||
for (i = 0; i < 2; i++) { | ||
load_opts.attach_btf_id = btf_id[i]; | ||
load_opts.attach_btf_obj_fd = btf_fd[i]; | ||
prog_fd[i] = bpf_prog_load(BPF_PROG_TYPE_TRACING, NULL, "GPL", | ||
trace_program, | ||
sizeof(trace_program) / sizeof(struct bpf_insn), | ||
&load_opts); | ||
if (!ASSERT_GE(prog_fd[i], 0, "bpf_prog_load")) | ||
goto out; | ||
|
||
/* If the verifier incorrectly resolves addresses of the | ||
* shadowed functions and uses the same address for both the | ||
* vmlinux and the bpf_testmod functions, this will fail on | ||
* attempting to create two trampolines for the same address, | ||
* which is forbidden. | ||
*/ | ||
link_fd[i] = bpf_link_create(prog_fd[i], 0, BPF_TRACE_FENTRY, NULL); | ||
if (!ASSERT_GE(link_fd[i], 0, "bpf_link_create")) | ||
goto out; | ||
} | ||
|
||
err = bpf_prog_test_run_opts(prog_fd[0], NULL); | ||
ASSERT_OK(err, "running test"); | ||
|
||
out: | ||
btf__free(vmlinux_btf); | ||
btf__free(mod_btf); | ||
for (i = 0; i < 2; i++) { | ||
if (btf_fd[i]) | ||
close(btf_fd[i]); | ||
if (prog_fd[i] > 0) | ||
close(prog_fd[i]); | ||
if (link_fd[i] > 0) | ||
close(link_fd[i]); | ||
} | ||
} |