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