forked from torvalds/linux
-
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: Add selftests for BPF_MODIFY_RETURN
Test for two scenarios: * When the fmod_ret program returns 0, the original function should be called along with fentry and fexit programs. * When the fmod_ret program returns a non-zero value, the original function should not be called, no side effect should be observed and fentry and fexit programs should be called. The result from the kernel function call and whether a side-effect is observed is returned via the retval attr of the BPF_PROG_TEST_RUN (bpf) syscall. Signed-off-by: KP Singh <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
- Loading branch information
Showing
3 changed files
with
135 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
/* | ||
* Copyright 2020 Google LLC. | ||
*/ | ||
|
||
#include <test_progs.h> | ||
#include "modify_return.skel.h" | ||
|
||
#define LOWER(x) ((x) & 0xffff) | ||
#define UPPER(x) ((x) >> 16) | ||
|
||
|
||
static void run_test(__u32 input_retval, __u16 want_side_effect, __s16 want_ret) | ||
{ | ||
struct modify_return *skel = NULL; | ||
int err, prog_fd; | ||
__u32 duration = 0, retval; | ||
__u16 side_effect; | ||
__s16 ret; | ||
|
||
skel = modify_return__open_and_load(); | ||
if (CHECK(!skel, "skel_load", "modify_return skeleton failed\n")) | ||
goto cleanup; | ||
|
||
err = modify_return__attach(skel); | ||
if (CHECK(err, "modify_return", "attach failed: %d\n", err)) | ||
goto cleanup; | ||
|
||
skel->bss->input_retval = input_retval; | ||
prog_fd = bpf_program__fd(skel->progs.fmod_ret_test); | ||
err = bpf_prog_test_run(prog_fd, 1, NULL, 0, NULL, 0, | ||
&retval, &duration); | ||
|
||
CHECK(err, "test_run", "err %d errno %d\n", err, errno); | ||
|
||
side_effect = UPPER(retval); | ||
ret = LOWER(retval); | ||
|
||
CHECK(ret != want_ret, "test_run", | ||
"unexpected ret: %d, expected: %d\n", ret, want_ret); | ||
CHECK(side_effect != want_side_effect, "modify_return", | ||
"unexpected side_effect: %d\n", side_effect); | ||
|
||
CHECK(skel->bss->fentry_result != 1, "modify_return", | ||
"fentry failed\n"); | ||
CHECK(skel->bss->fexit_result != 1, "modify_return", | ||
"fexit failed\n"); | ||
CHECK(skel->bss->fmod_ret_result != 1, "modify_return", | ||
"fmod_ret failed\n"); | ||
|
||
cleanup: | ||
modify_return__destroy(skel); | ||
} | ||
|
||
void test_modify_return(void) | ||
{ | ||
run_test(0 /* input_retval */, | ||
1 /* want_side_effect */, | ||
4 /* want_ret */); | ||
run_test(-EINVAL /* input_retval */, | ||
0 /* want_side_effect */, | ||
-EINVAL /* want_ret */); | ||
} | ||
|
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,49 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
/* | ||
* Copyright 2020 Google LLC. | ||
*/ | ||
|
||
#include <linux/bpf.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_tracing.h> | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
static int sequence = 0; | ||
__s32 input_retval = 0; | ||
|
||
__u64 fentry_result = 0; | ||
SEC("fentry/bpf_modify_return_test") | ||
int BPF_PROG(fentry_test, int a, __u64 b) | ||
{ | ||
sequence++; | ||
fentry_result = (sequence == 1); | ||
return 0; | ||
} | ||
|
||
__u64 fmod_ret_result = 0; | ||
SEC("fmod_ret/bpf_modify_return_test") | ||
int BPF_PROG(fmod_ret_test, int a, int *b, int ret) | ||
{ | ||
sequence++; | ||
/* This is the first fmod_ret program, the ret passed should be 0 */ | ||
fmod_ret_result = (sequence == 2 && ret == 0); | ||
return input_retval; | ||
} | ||
|
||
__u64 fexit_result = 0; | ||
SEC("fexit/bpf_modify_return_test") | ||
int BPF_PROG(fexit_test, int a, __u64 b, int ret) | ||
{ | ||
sequence++; | ||
/* If the input_reval is non-zero a successful modification should have | ||
* occurred. | ||
*/ | ||
if (input_retval) | ||
fexit_result = (sequence == 3 && ret == input_retval); | ||
else | ||
fexit_result = (sequence == 3 && ret == 4); | ||
|
||
return 0; | ||
} |