xref: /linux/tools/testing/selftests/bpf/progs/exceptions_fail.c (revision bfec8e88ff6022b056615ec71506703e7e54de82)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <vmlinux.h>
3 #include <bpf/bpf_tracing.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_core_read.h>
6 
7 #include "bpf_misc.h"
8 #include "bpf_experimental.h"
9 
10 extern void bpf_rcu_read_lock(void) __ksym;
11 extern void bpf_rcu_read_unlock(void) __ksym;
12 extern void bpf_preempt_disable(void) __ksym;
13 extern void bpf_preempt_enable(void) __ksym;
14 extern void bpf_local_irq_save(unsigned long *) __ksym;
15 extern void bpf_local_irq_restore(unsigned long *) __ksym;
16 
17 #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
18 
19 struct foo {
20 	struct bpf_rb_node node;
21 };
22 
23 struct hmap_elem {
24 	struct bpf_timer timer;
25 };
26 
27 struct {
28 	__uint(type, BPF_MAP_TYPE_HASH);
29 	__uint(max_entries, 64);
30 	__type(key, int);
31 	__type(value, struct hmap_elem);
32 } hmap SEC(".maps");
33 
34 private(A) struct bpf_spin_lock lock;
35 private(A) struct bpf_rb_root rbtree __contains(foo, node);
36 
37 __noinline void *exception_cb_bad_ret_type1(u64 cookie)
38 {
39 	return NULL;
40 }
41 
42 __noinline void exception_cb_bad_ret_type2(u64 cookie)
43 {
44 }
45 
46 __noinline int exception_cb_bad_arg_0(void)
47 {
48 	return 0;
49 }
50 
51 __noinline int exception_cb_bad_arg_2(int a, int b)
52 {
53 	return 0;
54 }
55 
56 __noinline int exception_cb_ok_arg_small(int a)
57 {
58 	return 0;
59 }
60 
61 SEC("?tc")
62 __exception_cb(exception_cb_bad_ret_type1)
63 __failure __msg("Global function exception_cb_bad_ret_type1() return value not void or scalar.")
64 int reject_exception_cb_type_1(struct __sk_buff *ctx)
65 {
66 	bpf_throw(0);
67 	return 0;
68 }
69 
70 SEC("?tc")
71 __exception_cb(exception_cb_bad_arg_0)
72 __failure __msg("exception cb only supports single integer argument")
73 int reject_exception_cb_type_2(struct __sk_buff *ctx)
74 {
75 	bpf_throw(0);
76 	return 0;
77 }
78 
79 SEC("?tc")
80 __exception_cb(exception_cb_bad_arg_2)
81 __failure __msg("exception cb only supports single integer argument")
82 int reject_exception_cb_type_3(struct __sk_buff *ctx)
83 {
84 	bpf_throw(0);
85 	return 0;
86 }
87 
88 SEC("?tc")
89 __exception_cb(exception_cb_ok_arg_small)
90 __success
91 int reject_exception_cb_type_4(struct __sk_buff *ctx)
92 {
93 	bpf_throw(0);
94 	return 0;
95 }
96 
97 SEC("?tc")
98 __exception_cb(exception_cb_bad_ret_type2)
99 __failure __msg("exception cb cannot return void")
100 int reject_exception_cb_type_5(struct __sk_buff *ctx)
101 {
102 	bpf_throw(0);
103 	return 0;
104 }
105 
106 __noinline
107 static int timer_cb(void *map, int *key, struct bpf_timer *timer)
108 {
109 	bpf_throw(0);
110 	return 0;
111 }
112 
113 SEC("?tc")
114 __failure __msg("cannot be called from callback subprog")
115 int reject_async_callback_throw(struct __sk_buff *ctx)
116 {
117 	struct hmap_elem *elem;
118 
119 	elem = bpf_map_lookup_elem(&hmap, &(int){0});
120 	if (!elem)
121 		return 0;
122 	return bpf_timer_set_callback(&elem->timer, timer_cb);
123 }
124 
125 __noinline static int subprog_lock(struct __sk_buff *ctx)
126 {
127 	volatile int ret = 0;
128 
129 	bpf_spin_lock(&lock);
130 	if (ctx->len)
131 		bpf_throw(0);
132 	return ret;
133 }
134 
135 SEC("?tc")
136 __failure __msg("function calls are not allowed while holding a lock")
137 int reject_with_lock(void *ctx)
138 {
139 	bpf_spin_lock(&lock);
140 	bpf_throw(0);
141 	return 0;
142 }
143 
144 SEC("?tc")
145 __failure __msg("function calls are not allowed while holding a lock")
146 int reject_subprog_with_lock(void *ctx)
147 {
148 	return subprog_lock(ctx);
149 }
150 
151 SEC("?tc")
152 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
153 int reject_with_rcu_read_lock(void *ctx)
154 {
155 	bpf_rcu_read_lock();
156 	bpf_throw(0);
157 	return 0;
158 }
159 
160 __noinline static int throwing_subprog(struct __sk_buff *ctx)
161 {
162 	if (ctx->len)
163 		bpf_throw(0);
164 	return 0;
165 }
166 
167 SEC("?tc")
168 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
169 int reject_subprog_with_rcu_read_lock(void *ctx)
170 {
171 	bpf_rcu_read_lock();
172 	throwing_subprog(ctx);
173 	bpf_rcu_read_unlock();
174 	return 0;
175 }
176 
177 static bool rbless(struct bpf_rb_node *n1, const struct bpf_rb_node *n2)
178 {
179 	bpf_throw(0);
180 	return true;
181 }
182 
183 SEC("?tc")
184 __failure __msg("function calls are not allowed while holding a lock")
185 int reject_with_rbtree_add_throw(void *ctx)
186 {
187 	struct foo *f;
188 
189 	f = bpf_obj_new(typeof(*f));
190 	if (!f)
191 		return 0;
192 	bpf_spin_lock(&lock);
193 	bpf_rbtree_add(&rbtree, &f->node, rbless);
194 	bpf_spin_unlock(&lock);
195 	return 0;
196 }
197 
198 SEC("?tc")
199 __failure __msg("Unreleased reference")
200 int reject_with_reference(void *ctx)
201 {
202 	struct foo *f;
203 
204 	f = bpf_obj_new(typeof(*f));
205 	if (!f)
206 		return 0;
207 	bpf_throw(0);
208 	return 0;
209 }
210 
211 __noinline static int subprog_ref(struct __sk_buff *ctx)
212 {
213 	struct foo *f;
214 
215 	f = bpf_obj_new(typeof(*f));
216 	if (!f)
217 		return 0;
218 	bpf_throw(0);
219 	return 0;
220 }
221 
222 __noinline static int subprog_cb_ref(u32 i, void *ctx)
223 {
224 	bpf_throw(0);
225 	return 0;
226 }
227 
228 SEC("?tc")
229 __failure __msg("Unreleased reference")
230 int reject_with_cb_reference(void *ctx)
231 {
232 	struct foo *f;
233 
234 	f = bpf_obj_new(typeof(*f));
235 	if (!f)
236 		return 0;
237 	bpf_loop(5, subprog_cb_ref, NULL, 0);
238 	bpf_obj_drop(f);
239 	return 0;
240 }
241 
242 SEC("?tc")
243 __failure __msg("cannot be called from callback")
244 int reject_with_cb(void *ctx)
245 {
246 	bpf_loop(5, subprog_cb_ref, NULL, 0);
247 	return 0;
248 }
249 
250 SEC("?tc")
251 __failure __msg("Unreleased reference")
252 int reject_with_subprog_reference(void *ctx)
253 {
254 	return subprog_ref(ctx) + 1;
255 }
256 
257 __noinline int throwing_exception_cb(u64 c)
258 {
259 	bpf_throw(0);
260 	return c;
261 }
262 
263 __noinline int exception_cb1(u64 c)
264 {
265 	return c;
266 }
267 
268 __noinline int exception_cb2(u64 c)
269 {
270 	return c;
271 }
272 
273 static __noinline int static_func(struct __sk_buff *ctx)
274 {
275 	return exception_cb1(ctx->tstamp);
276 }
277 
278 __noinline int global_func(struct __sk_buff *ctx)
279 {
280 	return exception_cb1(ctx->tstamp);
281 }
282 
283 SEC("?tc")
284 __exception_cb(throwing_exception_cb)
285 __failure __msg("cannot be called from callback subprog")
286 int reject_throwing_exception_cb(struct __sk_buff *ctx)
287 {
288 	return 0;
289 }
290 
291 SEC("?tc")
292 __exception_cb(exception_cb1)
293 __failure __msg("cannot call exception cb directly")
294 int reject_exception_cb_call_global_func(struct __sk_buff *ctx)
295 {
296 	return global_func(ctx);
297 }
298 
299 SEC("?tc")
300 __exception_cb(exception_cb1)
301 __failure __msg("cannot call exception cb directly")
302 int reject_exception_cb_call_static_func(struct __sk_buff *ctx)
303 {
304 	return static_func(ctx);
305 }
306 
307 SEC("?tc")
308 __exception_cb(exception_cb1)
309 __exception_cb(exception_cb2)
310 __failure __msg("multiple exception callback tags for main subprog")
311 int reject_multiple_exception_cb(struct __sk_buff *ctx)
312 {
313 	bpf_throw(0);
314 	return 16;
315 }
316 
317 __noinline int exception_cb_bad_ret(u64 c)
318 {
319 	return c;
320 }
321 
322 SEC("?fentry/bpf_check")
323 __exception_cb(exception_cb_bad_ret)
324 __failure __msg("At program exit the register R0 has unknown scalar value should")
325 int reject_set_exception_cb_bad_ret1(void *ctx)
326 {
327 	return 0;
328 }
329 
330 SEC("?fentry/bpf_check")
331 __failure __msg("At program exit the register R1 has smin=64 smax=64 should")
332 int reject_set_exception_cb_bad_ret2(void *ctx)
333 {
334 	bpf_throw(64);
335 	return 0;
336 }
337 
338 __noinline static int loop_cb1(u32 index, int *ctx)
339 {
340 	bpf_throw(0);
341 	return 0;
342 }
343 
344 __noinline static int loop_cb2(u32 index, int *ctx)
345 {
346 	bpf_throw(0);
347 	return 0;
348 }
349 
350 SEC("?tc")
351 __failure __msg("cannot be called from callback")
352 int reject_exception_throw_cb(struct __sk_buff *ctx)
353 {
354 	bpf_loop(5, loop_cb1, NULL, 0);
355 	return 0;
356 }
357 
358 SEC("?tc")
359 __failure __msg("cannot be called from callback")
360 int reject_exception_throw_cb_diff(struct __sk_buff *ctx)
361 {
362 	if (ctx->protocol)
363 		bpf_loop(5, loop_cb1, NULL, 0);
364 	else
365 		bpf_loop(5, loop_cb2, NULL, 0);
366 	return 0;
367 }
368 
369 __weak
370 void foo(void)
371 {
372 	bpf_throw(1);
373 }
374 
375 SEC("?fentry/bpf_check")
376 __failure __msg("At program exit the register R1 has smin=1 smax=1 should")
377 int reject_out_of_range_global_throw(struct __sk_buff *skb)
378 {
379 	foo();
380 
381 	return 0;
382 }
383 
384 __noinline static int always_throws(void)
385 {
386 	bpf_throw(0);
387 	return 0;
388 }
389 
390 __noinline static int rcu_lock_then_throw(void)
391 {
392 	bpf_rcu_read_lock();
393 	bpf_throw(0);
394 	return 0;
395 }
396 
397 SEC("?tc")
398 __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region")
399 int reject_subprog_rcu_lock_throw(void *ctx)
400 {
401 	rcu_lock_then_throw();
402 	return 0;
403 }
404 
405 SEC("?tc")
406 __failure __msg("bpf_throw cannot be used inside bpf_preempt_disable-ed region")
407 int reject_subprog_throw_preempt_lock(void *ctx)
408 {
409 	bpf_preempt_disable();
410 	always_throws();
411 	bpf_preempt_enable();
412 	return 0;
413 }
414 
415 SEC("?tc")
416 __failure __msg("bpf_throw cannot be used inside bpf_local_irq_save-ed region")
417 int reject_subprog_throw_irq_lock(void *ctx)
418 {
419 	unsigned long flags;
420 
421 	bpf_local_irq_save(&flags);
422 	always_throws();
423 	bpf_local_irq_restore(&flags);
424 	return 0;
425 }
426 
427 char _license[] SEC("license") = "GPL";
428