Skip to content

Commit 7c5f7b1

Browse files
juntongdengAlexei Starovoitov
authored andcommitted
selftests/bpf: Add tests for iter next method returning valid pointer
This patch adds test cases for iter next method returning valid pointer, which can also used as usage examples. Currently iter next method should return valid pointer. iter_next_trusted is the correct usage and test if iter next method return valid pointer. bpf_iter_task_vma_next has KF_RET_NULL flag, so the returned pointer may be NULL. We need to check if the pointer is NULL before using it. iter_next_trusted_or_null is the incorrect usage. There is no checking before using the pointer, so it will be rejected by the verifier. iter_next_rcu and iter_next_rcu_or_null are similar test cases for KF_RCU_PROTECTED iterators. iter_next_rcu_not_trusted is used to test that the pointer returned by iter next method of KF_RCU_PROTECTED iterator cannot be passed in KF_TRUSTED_ARGS kfuncs. iter_next_ptr_mem_not_trusted is used to test that base type PTR_TO_MEM should not be combined with type flag PTR_TRUSTED. Signed-off-by: Juntong Deng <[email protected]> Link: https://lore.kernel.org/r/AM6PR03MB5848709758F6922F02AF9F1F99962@AM6PR03MB5848.eurprd03.prod.outlook.com Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 4cc8c50 commit 7c5f7b1

File tree

4 files changed

+154
-1
lines changed

4 files changed

+154
-1
lines changed

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ __bpf_kfunc void bpf_kfunc_nested_release_test(struct sk_buff *ptr)
198198
{
199199
}
200200

201+
__bpf_kfunc void bpf_kfunc_trusted_vma_test(struct vm_area_struct *ptr)
202+
{
203+
}
204+
205+
__bpf_kfunc void bpf_kfunc_trusted_task_test(struct task_struct *ptr)
206+
{
207+
}
208+
209+
__bpf_kfunc void bpf_kfunc_trusted_num_test(int *ptr)
210+
{
211+
}
212+
213+
__bpf_kfunc void bpf_kfunc_rcu_task_test(struct task_struct *ptr)
214+
{
215+
}
216+
201217
__bpf_kfunc struct bpf_testmod_ctx *
202218
bpf_testmod_ctx_create(int *err)
203219
{
@@ -559,6 +575,10 @@ BTF_ID_FLAGS(func, bpf_kfunc_dynptr_test)
559575
BTF_ID_FLAGS(func, bpf_kfunc_nested_acquire_nonzero_offset_test, KF_ACQUIRE)
560576
BTF_ID_FLAGS(func, bpf_kfunc_nested_acquire_zero_offset_test, KF_ACQUIRE)
561577
BTF_ID_FLAGS(func, bpf_kfunc_nested_release_test, KF_RELEASE)
578+
BTF_ID_FLAGS(func, bpf_kfunc_trusted_vma_test, KF_TRUSTED_ARGS)
579+
BTF_ID_FLAGS(func, bpf_kfunc_trusted_task_test, KF_TRUSTED_ARGS)
580+
BTF_ID_FLAGS(func, bpf_kfunc_trusted_num_test, KF_TRUSTED_ARGS)
581+
BTF_ID_FLAGS(func, bpf_kfunc_rcu_task_test, KF_RCU)
562582
BTF_ID_FLAGS(func, bpf_testmod_ctx_create, KF_ACQUIRE | KF_RET_NULL)
563583
BTF_ID_FLAGS(func, bpf_testmod_ctx_release, KF_RELEASE)
564584
BTF_KFUNCS_END(bpf_testmod_common_kfunc_ids)

tools/testing/selftests/bpf/bpf_testmod/bpf_testmod_kfunc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,9 @@ int bpf_kfunc_st_ops_test_epilogue(struct st_ops_args *args) __ksym;
154154
int bpf_kfunc_st_ops_test_pro_epilogue(struct st_ops_args *args) __ksym;
155155
int bpf_kfunc_st_ops_inc10(struct st_ops_args *args) __ksym;
156156

157+
void bpf_kfunc_trusted_vma_test(struct vm_area_struct *ptr) __ksym;
158+
void bpf_kfunc_trusted_task_test(struct task_struct *ptr) __ksym;
159+
void bpf_kfunc_trusted_num_test(int *ptr) __ksym;
160+
void bpf_kfunc_rcu_task_test(struct task_struct *ptr) __ksym;
161+
157162
#endif /* _BPF_TESTMOD_KFUNC_H */

tools/testing/selftests/bpf/prog_tests/iters.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "iters_state_safety.skel.h"
1515
#include "iters_looping.skel.h"
1616
#include "iters_num.skel.h"
17+
#include "iters_testmod.skel.h"
1718
#include "iters_testmod_seq.skel.h"
1819
#include "iters_task_vma.skel.h"
1920
#include "iters_task.skel.h"
@@ -297,8 +298,10 @@ void test_iters(void)
297298
RUN_TESTS(iters);
298299
RUN_TESTS(iters_css_task);
299300

300-
if (env.has_testmod)
301+
if (env.has_testmod) {
302+
RUN_TESTS(iters_testmod);
301303
RUN_TESTS(iters_testmod_seq);
304+
}
302305

303306
if (test__start_subtest("num"))
304307
subtest_num_iters();
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include "vmlinux.h"
4+
#include "bpf_experimental.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include "bpf_misc.h"
7+
#include "../bpf_testmod/bpf_testmod_kfunc.h"
8+
9+
char _license[] SEC("license") = "GPL";
10+
11+
SEC("raw_tp/sys_enter")
12+
__success
13+
int iter_next_trusted(const void *ctx)
14+
{
15+
struct task_struct *cur_task = bpf_get_current_task_btf();
16+
struct bpf_iter_task_vma vma_it;
17+
struct vm_area_struct *vma_ptr;
18+
19+
bpf_iter_task_vma_new(&vma_it, cur_task, 0);
20+
21+
vma_ptr = bpf_iter_task_vma_next(&vma_it);
22+
if (vma_ptr == NULL)
23+
goto out;
24+
25+
bpf_kfunc_trusted_vma_test(vma_ptr);
26+
out:
27+
bpf_iter_task_vma_destroy(&vma_it);
28+
return 0;
29+
}
30+
31+
SEC("raw_tp/sys_enter")
32+
__failure __msg("Possibly NULL pointer passed to trusted arg0")
33+
int iter_next_trusted_or_null(const void *ctx)
34+
{
35+
struct task_struct *cur_task = bpf_get_current_task_btf();
36+
struct bpf_iter_task_vma vma_it;
37+
struct vm_area_struct *vma_ptr;
38+
39+
bpf_iter_task_vma_new(&vma_it, cur_task, 0);
40+
41+
vma_ptr = bpf_iter_task_vma_next(&vma_it);
42+
43+
bpf_kfunc_trusted_vma_test(vma_ptr);
44+
45+
bpf_iter_task_vma_destroy(&vma_it);
46+
return 0;
47+
}
48+
49+
SEC("raw_tp/sys_enter")
50+
__success
51+
int iter_next_rcu(const void *ctx)
52+
{
53+
struct task_struct *cur_task = bpf_get_current_task_btf();
54+
struct bpf_iter_task task_it;
55+
struct task_struct *task_ptr;
56+
57+
bpf_iter_task_new(&task_it, cur_task, 0);
58+
59+
task_ptr = bpf_iter_task_next(&task_it);
60+
if (task_ptr == NULL)
61+
goto out;
62+
63+
bpf_kfunc_rcu_task_test(task_ptr);
64+
out:
65+
bpf_iter_task_destroy(&task_it);
66+
return 0;
67+
}
68+
69+
SEC("raw_tp/sys_enter")
70+
__failure __msg("Possibly NULL pointer passed to trusted arg0")
71+
int iter_next_rcu_or_null(const void *ctx)
72+
{
73+
struct task_struct *cur_task = bpf_get_current_task_btf();
74+
struct bpf_iter_task task_it;
75+
struct task_struct *task_ptr;
76+
77+
bpf_iter_task_new(&task_it, cur_task, 0);
78+
79+
task_ptr = bpf_iter_task_next(&task_it);
80+
81+
bpf_kfunc_rcu_task_test(task_ptr);
82+
83+
bpf_iter_task_destroy(&task_it);
84+
return 0;
85+
}
86+
87+
SEC("raw_tp/sys_enter")
88+
__failure __msg("R1 must be referenced or trusted")
89+
int iter_next_rcu_not_trusted(const void *ctx)
90+
{
91+
struct task_struct *cur_task = bpf_get_current_task_btf();
92+
struct bpf_iter_task task_it;
93+
struct task_struct *task_ptr;
94+
95+
bpf_iter_task_new(&task_it, cur_task, 0);
96+
97+
task_ptr = bpf_iter_task_next(&task_it);
98+
if (task_ptr == NULL)
99+
goto out;
100+
101+
bpf_kfunc_trusted_task_test(task_ptr);
102+
out:
103+
bpf_iter_task_destroy(&task_it);
104+
return 0;
105+
}
106+
107+
SEC("raw_tp/sys_enter")
108+
__failure __msg("R1 cannot write into rdonly_mem")
109+
/* Message should not be 'R1 cannot write into rdonly_trusted_mem' */
110+
int iter_next_ptr_mem_not_trusted(const void *ctx)
111+
{
112+
struct bpf_iter_num num_it;
113+
int *num_ptr;
114+
115+
bpf_iter_num_new(&num_it, 0, 10);
116+
117+
num_ptr = bpf_iter_num_next(&num_it);
118+
if (num_ptr == NULL)
119+
goto out;
120+
121+
bpf_kfunc_trusted_num_test(num_ptr);
122+
out:
123+
bpf_iter_num_destroy(&num_it);
124+
return 0;
125+
}

0 commit comments

Comments
 (0)