xref: /linux/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c (revision 0a91336e287ca2557fead5221d2c79e0effd034e)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 
4 #include <vmlinux.h>
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
7 #include <bpf/bpf_core_read.h>
8 #include "bpf_misc.h"
9 #include "xdp_metadata.h"
10 #include "bpf_kfuncs.h"
11 
12 extern struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym __weak;
13 extern void bpf_task_release(struct task_struct *p) __ksym __weak;
14 
subprog_trusted_task_nullable(struct task_struct * task __arg_trusted __arg_nullable)15 __weak int subprog_trusted_task_nullable(struct task_struct *task __arg_trusted __arg_nullable)
16 {
17 	if (!task)
18 		return 0;
19 	return task->pid + task->tgid;
20 }
21 
subprog_trusted_task_nullable_extra_layer(struct task_struct * task __arg_trusted __arg_nullable)22 __weak int subprog_trusted_task_nullable_extra_layer(struct task_struct *task __arg_trusted __arg_nullable)
23 {
24 	return subprog_trusted_task_nullable(task) + subprog_trusted_task_nullable(NULL);
25 }
26 
27 SEC("?tp_btf/task_newtask")
28 __success __log_level(2)
29 __msg("Validating subprog_trusted_task_nullable() func#1...")
30 __msg(": R1=trusted_ptr_or_null_task_struct(")
trusted_task_arg_nullable(void * ctx)31 int trusted_task_arg_nullable(void *ctx)
32 {
33 	struct task_struct *t1 = bpf_get_current_task_btf();
34 	struct task_struct *t2 = bpf_task_acquire(t1);
35 	int res = 0;
36 
37 	/* known NULL */
38 	res += subprog_trusted_task_nullable(NULL);
39 
40 	/* known non-NULL */
41 	res += subprog_trusted_task_nullable(t1);
42 	res += subprog_trusted_task_nullable_extra_layer(t1);
43 
44 	/* unknown if NULL or not */
45 	res += subprog_trusted_task_nullable(t2);
46 	res += subprog_trusted_task_nullable_extra_layer(t2);
47 
48 	if (t2) {
49 		/* known non-NULL after explicit NULL check, just in case */
50 		res += subprog_trusted_task_nullable(t2);
51 		res += subprog_trusted_task_nullable_extra_layer(t2);
52 
53 		bpf_task_release(t2);
54 	}
55 
56 	return res;
57 }
58 
subprog_trusted_task_nonnull(struct task_struct * task __arg_trusted)59 __weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)
60 {
61 	return task->pid + task->tgid;
62 }
63 
64 SEC("?kprobe")
65 __failure __log_level(2)
66 __msg("R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_")
67 __msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')")
trusted_task_arg_nonnull_fail1(void * ctx)68 int trusted_task_arg_nonnull_fail1(void *ctx)
69 {
70 	return subprog_trusted_task_nonnull(NULL);
71 }
72 
73 SEC("?tp_btf/task_newtask")
74 __failure __log_level(2)
75 __msg("R1 type=ptr_or_null_ expected=ptr_, trusted_ptr_, rcu_ptr_")
76 __msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')")
trusted_task_arg_nonnull_fail2(void * ctx)77 int trusted_task_arg_nonnull_fail2(void *ctx)
78 {
79 	struct task_struct *t = bpf_get_current_task_btf();
80 	struct task_struct *nullable;
81 	int res;
82 
83 	nullable = bpf_task_acquire(t);
84 
85 	 /* should fail, PTR_TO_BTF_ID_OR_NULL */
86 	res = subprog_trusted_task_nonnull(nullable);
87 
88 	if (nullable)
89 		bpf_task_release(nullable);
90 
91 	return res;
92 }
93 
94 SEC("?kprobe")
95 __success __log_level(2)
96 __msg("Validating subprog_trusted_task_nonnull() func#1...")
97 __msg(": R1=trusted_ptr_task_struct(")
trusted_task_arg_nonnull(void * ctx)98 int trusted_task_arg_nonnull(void *ctx)
99 {
100 	struct task_struct *t = bpf_get_current_task_btf();
101 
102 	return subprog_trusted_task_nonnull(t);
103 }
104 
105 struct task_struct___local {} __attribute__((preserve_access_index));
106 
subprog_nullable_task_flavor(struct task_struct___local * task __arg_trusted __arg_nullable)107 __weak int subprog_nullable_task_flavor(
108 	struct task_struct___local *task __arg_trusted __arg_nullable)
109 {
110 	char buf[16];
111 
112 	if (!task)
113 		return 0;
114 
115 	return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0);
116 }
117 
118 SEC("?uprobe.s")
119 __success __log_level(2)
120 __msg("Validating subprog_nullable_task_flavor() func#1...")
121 __msg(": R1=trusted_ptr_or_null_task_struct(")
flavor_ptr_nullable(void * ctx)122 int flavor_ptr_nullable(void *ctx)
123 {
124 	struct task_struct___local *t = (void *)bpf_get_current_task_btf();
125 
126 	return subprog_nullable_task_flavor(t);
127 }
128 
subprog_nonnull_task_flavor(struct task_struct___local * task __arg_trusted)129 __weak int subprog_nonnull_task_flavor(struct task_struct___local *task __arg_trusted)
130 {
131 	char buf[16];
132 
133 	return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0);
134 }
135 
136 SEC("?uprobe.s")
137 __success __log_level(2)
138 __msg("Validating subprog_nonnull_task_flavor() func#1...")
139 __msg(": R1=trusted_ptr_task_struct(")
flavor_ptr_nonnull(void * ctx)140 int flavor_ptr_nonnull(void *ctx)
141 {
142 	struct task_struct *t = bpf_get_current_task_btf();
143 
144 	return subprog_nonnull_task_flavor((void *)t);
145 }
146 
subprog_trusted_destroy(struct task_struct * task __arg_trusted)147 __weak int subprog_trusted_destroy(struct task_struct *task __arg_trusted)
148 {
149 	bpf_task_release(task); /* should be rejected */
150 
151 	return 0;
152 }
153 
154 SEC("?tp_btf/task_newtask")
155 __failure __log_level(2)
156 __msg("release kernel function bpf_task_release expects refcounted PTR_TO_BTF_ID")
BPF_PROG(trusted_destroy_fail,struct task_struct * task,u64 clone_flags)157 int BPF_PROG(trusted_destroy_fail, struct task_struct *task, u64 clone_flags)
158 {
159 	return subprog_trusted_destroy(task);
160 }
161 
subprog_trusted_acq_rel(struct task_struct * task __arg_trusted)162 __weak int subprog_trusted_acq_rel(struct task_struct *task __arg_trusted)
163 {
164 	struct task_struct *owned;
165 
166 	owned = bpf_task_acquire(task);
167 	if (!owned)
168 		return 0;
169 
170 	bpf_task_release(owned); /* this one is OK, we acquired it locally */
171 
172 	return 0;
173 }
174 
175 SEC("?tp_btf/task_newtask")
176 __success __log_level(2)
BPF_PROG(trusted_acq_rel,struct task_struct * task,u64 clone_flags)177 int BPF_PROG(trusted_acq_rel, struct task_struct *task, u64 clone_flags)
178 {
179 	return subprog_trusted_acq_rel(task);
180 }
181 
subprog_untrusted_bad_tags(struct task_struct * task __arg_untrusted __arg_nullable)182 __weak int subprog_untrusted_bad_tags(struct task_struct *task __arg_untrusted __arg_nullable)
183 {
184 	return task->pid;
185 }
186 
187 SEC("tp_btf/sys_enter")
188 __failure
189 __msg("arg#0 untrusted cannot be combined with any other tags")
untrusted_bad_tags(void * ctx)190 int untrusted_bad_tags(void *ctx)
191 {
192 	return subprog_untrusted_bad_tags(0);
193 }
194 
195 struct local_type_wont_be_accepted {};
196 
subprog_untrusted_bad_type(struct local_type_wont_be_accepted * p __arg_untrusted)197 __weak int subprog_untrusted_bad_type(struct local_type_wont_be_accepted *p __arg_untrusted)
198 {
199 	return 0;
200 }
201 
202 SEC("tp_btf/sys_enter")
203 __failure
204 __msg("arg#0 reference type('STRUCT local_type_wont_be_accepted') has no matches")
untrusted_bad_type(void * ctx)205 int untrusted_bad_type(void *ctx)
206 {
207 	return subprog_untrusted_bad_type(bpf_rdonly_cast(0, 0));
208 }
209 
subprog_untrusted(const volatile struct task_struct * restrict task __arg_untrusted)210 __weak int subprog_untrusted(const volatile struct task_struct *restrict task __arg_untrusted)
211 {
212 	return task->pid;
213 }
214 
215 SEC("tp_btf/sys_enter")
216 __success
217 __log_level(2)
218 __msg("r1 = {{.*}}; {{.*}}R1_w=trusted_ptr_task_struct()")
219 __msg("Func#1 ('subprog_untrusted') is global and assumed valid.")
220 __msg("Validating subprog_untrusted() func#1...")
221 __msg(": R1=untrusted_ptr_task_struct")
trusted_to_untrusted(void * ctx)222 int trusted_to_untrusted(void *ctx)
223 {
224 	return subprog_untrusted(bpf_get_current_task_btf());
225 }
226 
227 char mem[16];
228 u32 off;
229 
230 SEC("tp_btf/sys_enter")
231 __success
anything_to_untrusted(void * ctx)232 int anything_to_untrusted(void *ctx)
233 {
234 	/* untrusted to untrusted */
235 	subprog_untrusted(bpf_core_cast(0, struct task_struct));
236 	/* wrong type to untrusted */
237 	subprog_untrusted((void *)bpf_core_cast(0, struct bpf_verifier_env));
238 	/* map value to untrusted */
239 	subprog_untrusted((void *)mem);
240 	/* scalar to untrusted */
241 	subprog_untrusted(0);
242 	/* variable offset to untrusted (map) */
243 	subprog_untrusted((void *)mem + off);
244 	/* variable offset to untrusted (trusted) */
245 	subprog_untrusted((void *)bpf_get_current_task_btf() + off);
246 	return 0;
247 }
248 
subprog_untrusted2(struct task_struct * task __arg_untrusted)249 __weak int subprog_untrusted2(struct task_struct *task __arg_untrusted)
250 {
251 	return subprog_trusted_task_nullable(task);
252 }
253 
254 SEC("tp_btf/sys_enter")
255 __failure
256 __msg("R1 type=untrusted_ptr_ expected=ptr_, trusted_ptr_, rcu_ptr_")
257 __msg("Caller passes invalid args into func#{{.*}} ('subprog_trusted_task_nullable')")
untrusted_to_trusted(void * ctx)258 int untrusted_to_trusted(void *ctx)
259 {
260 	return subprog_untrusted2(bpf_get_current_task_btf());
261 }
262 
subprog_void_untrusted(void * p __arg_untrusted)263 __weak int subprog_void_untrusted(void *p __arg_untrusted)
264 {
265 	return *(int *)p;
266 }
267 
subprog_char_untrusted(char * p __arg_untrusted)268 __weak int subprog_char_untrusted(char *p __arg_untrusted)
269 {
270 	return *(int *)p;
271 }
272 
subprog_enum_untrusted(enum bpf_attach_type * p __arg_untrusted)273 __weak int subprog_enum_untrusted(enum bpf_attach_type *p __arg_untrusted)
274 {
275 	return *(int *)p;
276 }
277 
278 SEC("tp_btf/sys_enter")
279 __success
280 __log_level(2)
281 __msg("r1 = {{.*}}; {{.*}}R1_w=trusted_ptr_task_struct()")
282 __msg("Func#1 ('subprog_void_untrusted') is global and assumed valid.")
283 __msg("Validating subprog_void_untrusted() func#1...")
284 __msg(": R1=rdonly_untrusted_mem(sz=0)")
trusted_to_untrusted_mem(void * ctx)285 int trusted_to_untrusted_mem(void *ctx)
286 {
287 	return subprog_void_untrusted(bpf_get_current_task_btf());
288 }
289 
290 SEC("tp_btf/sys_enter")
291 __success
anything_to_untrusted_mem(void * ctx)292 int anything_to_untrusted_mem(void *ctx)
293 {
294 	/* untrusted to untrusted mem */
295 	subprog_void_untrusted(bpf_core_cast(0, struct task_struct));
296 	/* map value to untrusted mem */
297 	subprog_void_untrusted(mem);
298 	/* scalar to untrusted mem */
299 	subprog_void_untrusted(0);
300 	/* variable offset to untrusted mem (map) */
301 	subprog_void_untrusted((void *)mem + off);
302 	/* variable offset to untrusted mem (trusted) */
303 	subprog_void_untrusted(bpf_get_current_task_btf() + off);
304 	/* variable offset to untrusted char/enum (map) */
305 	subprog_char_untrusted(mem + off);
306 	subprog_enum_untrusted((void *)mem + off);
307 	return 0;
308 }
309 
310 char _license[] SEC("license") = "GPL";
311