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