File Index
Files and directories
Sign in
FILE

verifier_global_ptr_args.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/verifier_global_ptr_args.c C
  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
 12extern struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym __weak;
 13extern void bpf_task_release(struct task_struct *p) __ksym __weak;
 14
 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
 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
 27SEC("?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(")
 31int 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
 59__weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)
 60{
 61	return task->pid + task->tgid;
 62}
 63
 64SEC("?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')")
 68int trusted_task_arg_nonnull_fail1(void *ctx)
 69{
 70	return subprog_trusted_task_nonnull(NULL);
 71}
 72
 73SEC("?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')")
 77int 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
 94SEC("?kprobe")
 95__success __log_level(2)
 96__msg("Validating subprog_trusted_task_nonnull() func#1...")
 97__msg(": R1=trusted_ptr_task_struct(")
 98int 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
105struct task_struct___local {} __attribute__((preserve_access_index));
106
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
118SEC("?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(")
122int 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
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
136SEC("?uprobe.s")
137__success __log_level(2)
138__msg("Validating subprog_nonnull_task_flavor() func#1...")
139__msg(": R1=trusted_ptr_task_struct(")
140int 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
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
154SEC("?tp_btf/task_newtask")
155__failure __log_level(2)
156__msg("release kernel function bpf_task_release expects refcounted PTR_TO_BTF_ID")
157int BPF_PROG(trusted_destroy_fail, struct task_struct *task, u64 clone_flags)
158{
159	return subprog_trusted_destroy(task);
160}
161
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
175SEC("?tp_btf/task_newtask")
176__success __log_level(2)
177int BPF_PROG(trusted_acq_rel, struct task_struct *task, u64 clone_flags)
178{
179	return subprog_trusted_acq_rel(task);
180}
181
182__weak int subprog_untrusted_bad_tags(struct task_struct *task __arg_untrusted __arg_nullable)
183{
184	return task->pid;
185}
186
187SEC("tp_btf/sys_enter")
188__failure
189__msg("arg#0 untrusted cannot be combined with any other tags")
190int untrusted_bad_tags(void *ctx)
191{
192	return subprog_untrusted_bad_tags(0);
193}
194
195struct local_type_wont_be_accepted {};
196
197__weak int subprog_untrusted_bad_type(struct local_type_wont_be_accepted *p __arg_untrusted)
198{
199	return 0;
200}
201
202SEC("tp_btf/sys_enter")
203__failure
204__msg("arg#0 reference type('STRUCT local_type_wont_be_accepted') has no matches")
205int untrusted_bad_type(void *ctx)
206{
207	return subprog_untrusted_bad_type(bpf_rdonly_cast(0, 0));
208}
209
210__weak int subprog_untrusted(const volatile struct task_struct *restrict task __arg_untrusted)
211{
212	return task->pid;
213}
214
215SEC("tp_btf/sys_enter")
216__success
217__log_level(2)
218__msg("r1 = {{.*}}; {{.*}}R1=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")
222int trusted_to_untrusted(void *ctx)
223{
224	return subprog_untrusted(bpf_get_current_task_btf());
225}
226
227char mem[16];
228u32 offset;
229
230SEC("tp_btf/sys_enter")
231__success
232int 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 + offset);
244	/* variable offset to untrusted (trusted) */
245	subprog_untrusted((void *)bpf_get_current_task_btf() + offset);
246	return 0;
247}
248
249__weak int subprog_untrusted2(struct task_struct *task __arg_untrusted)
250{
251	return subprog_trusted_task_nullable(task);
252}
253
254SEC("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')")
258int untrusted_to_trusted(void *ctx)
259{
260	return subprog_untrusted2(bpf_get_current_task_btf());
261}
262
263__weak int subprog_void_untrusted(void *p __arg_untrusted)
264{
265	return *(int *)p;
266}
267
268__weak int subprog_char_untrusted(char *p __arg_untrusted)
269{
270	return *(int *)p;
271}
272
273__weak int subprog_enum_untrusted(enum bpf_attach_type *p __arg_untrusted)
274{
275	return *(int *)p;
276}
277
278SEC("tp_btf/sys_enter")
279__success
280__log_level(2)
281__msg("r1 = {{.*}}; {{.*}}R1=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)")
285int trusted_to_untrusted_mem(void *ctx)
286{
287	return subprog_void_untrusted(bpf_get_current_task_btf());
288}
289
290SEC("tp_btf/sys_enter")
291__success
292int 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 + offset);
302	/* variable offset to untrusted mem (trusted) */
303	subprog_void_untrusted(bpf_get_current_task_btf() + offset);
304	/* variable offset to untrusted char/enum (map) */
305	subprog_char_untrusted(mem + offset);
306	subprog_enum_untrusted((void *)mem + offset);
307	return 0;
308}
309
310char _license[] SEC("license") = "GPL";
~/ Read-only file preview.