-
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: Test referenced kptr arguments of struct_ops programs
Test referenced kptr acquired through struct_ops argument tagged with "__ref". The success case checks whether 1) a reference to the correct type is acquired, and 2) the referenced kptr argument can be accessed in multiple paths as long as it hasn't been released. In the fail cases, we first confirm that a referenced kptr acquried through a struct_ops argument is not allowed to be leaked. Then, we make sure this new referenced kptr acquiring mechanism does not accidentally allow referenced kptrs to flow into global subprograms through their arguments. Signed-off-by: Amery Hung <amery.hung@bytedance.com> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Acked-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://lore.kernel.org/r/20250217190640.1748177-4-ameryhung@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Amery Hung
authored and
Alexei Starovoitov
committed
Feb 18, 2025
1 parent
a687df2
commit 6991ec6
Showing
6 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
tools/testing/selftests/bpf/prog_tests/test_struct_ops_refcounted.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,12 @@ | ||
#include <test_progs.h> | ||
|
||
#include "struct_ops_refcounted.skel.h" | ||
#include "struct_ops_refcounted_fail__ref_leak.skel.h" | ||
#include "struct_ops_refcounted_fail__global_subprog.skel.h" | ||
|
||
void test_struct_ops_refcounted(void) | ||
{ | ||
RUN_TESTS(struct_ops_refcounted); | ||
RUN_TESTS(struct_ops_refcounted_fail__ref_leak); | ||
RUN_TESTS(struct_ops_refcounted_fail__global_subprog); | ||
} |
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,31 @@ | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "../test_kmods/bpf_testmod.h" | ||
#include "bpf_misc.h" | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
__attribute__((nomerge)) extern void bpf_task_release(struct task_struct *p) __ksym; | ||
|
||
/* This is a test BPF program that uses struct_ops to access a referenced | ||
* kptr argument. This is a test for the verifier to ensure that it | ||
* 1) recongnizes the task as a referenced object (i.e., ref_obj_id > 0), and | ||
* 2) the same reference can be acquired from multiple paths as long as it | ||
* has not been released. | ||
*/ | ||
SEC("struct_ops/test_refcounted") | ||
int BPF_PROG(refcounted, int dummy, struct task_struct *task) | ||
{ | ||
if (dummy == 1) | ||
bpf_task_release(task); | ||
else | ||
bpf_task_release(task); | ||
return 0; | ||
} | ||
|
||
SEC(".struct_ops.link") | ||
struct bpf_testmod_ops testmod_refcounted = { | ||
.test_refcounted = (void *)refcounted, | ||
}; | ||
|
||
|
39 changes: 39 additions & 0 deletions
39
tools/testing/selftests/bpf/progs/struct_ops_refcounted_fail__global_subprog.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,39 @@ | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "../test_kmods/bpf_testmod.h" | ||
#include "bpf_misc.h" | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
extern void bpf_task_release(struct task_struct *p) __ksym; | ||
|
||
__noinline int subprog_release(__u64 *ctx __arg_ctx) | ||
{ | ||
struct task_struct *task = (struct task_struct *)ctx[1]; | ||
int dummy = (int)ctx[0]; | ||
|
||
bpf_task_release(task); | ||
|
||
return dummy + 1; | ||
} | ||
|
||
/* Test that the verifier rejects a program that contains a global | ||
* subprogram with referenced kptr arguments | ||
*/ | ||
SEC("struct_ops/test_refcounted") | ||
__failure __log_level(2) | ||
__msg("Validating subprog_release() func#1...") | ||
__msg("invalid bpf_context access off=8. Reference may already be released") | ||
int refcounted_fail__global_subprog(unsigned long long *ctx) | ||
{ | ||
struct task_struct *task = (struct task_struct *)ctx[1]; | ||
|
||
bpf_task_release(task); | ||
|
||
return subprog_release(ctx); | ||
} | ||
|
||
SEC(".struct_ops.link") | ||
struct bpf_testmod_ops testmod_ref_acquire = { | ||
.test_refcounted = (void *)refcounted_fail__global_subprog, | ||
}; |
22 changes: 22 additions & 0 deletions
22
tools/testing/selftests/bpf/progs/struct_ops_refcounted_fail__ref_leak.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,22 @@ | ||
#include <vmlinux.h> | ||
#include <bpf/bpf_tracing.h> | ||
#include "../test_kmods/bpf_testmod.h" | ||
#include "bpf_misc.h" | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
/* Test that the verifier rejects a program that acquires a referenced | ||
* kptr through context without releasing the reference | ||
*/ | ||
SEC("struct_ops/test_refcounted") | ||
__failure __msg("Unreleased reference id=1 alloc_insn=0") | ||
int BPF_PROG(refcounted_fail__ref_leak, int dummy, | ||
struct task_struct *task) | ||
{ | ||
return 0; | ||
} | ||
|
||
SEC(".struct_ops.link") | ||
struct bpf_testmod_ops testmod_ref_acquire = { | ||
.test_refcounted = (void *)refcounted_fail__ref_leak, | ||
}; |
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