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
exception_cb_bad_ret_type(u64 cookie)32 __noinline void *exception_cb_bad_ret_type(u64 cookie)
33 {
34 return NULL;
35 }
36
exception_cb_bad_arg_0(void)37 __noinline int exception_cb_bad_arg_0(void)
38 {
39 return 0;
40 }
41
exception_cb_bad_arg_2(int a,int b)42 __noinline int exception_cb_bad_arg_2(int a, int b)
43 {
44 return 0;
45 }
46
exception_cb_ok_arg_small(int a)47 __noinline int exception_cb_ok_arg_small(int a)
48 {
49 return 0;
50 }
51
52 SEC("?tc")
__exception_cb(exception_cb_bad_ret_type)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")
__exception_cb(exception_cb_bad_arg_0)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")
__exception_cb(exception_cb_bad_arg_2)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")
__exception_cb(exception_cb_ok_arg_small)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
timer_cb(void * map,int * key,struct bpf_timer * timer)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")
reject_async_callback_throw(struct __sk_buff * ctx)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
subprog_lock(struct __sk_buff * ctx)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")
reject_with_lock(void * ctx)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")
reject_subprog_with_lock(void * ctx)128 int reject_subprog_with_lock(void *ctx)
129 {
130 return subprog_lock(ctx);
131 }
132
133 SEC("?tc")
134 __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region")
reject_with_rcu_read_lock(void * ctx)135 int reject_with_rcu_read_lock(void *ctx)
136 {
137 bpf_rcu_read_lock();
138 bpf_throw(0);
139 return 0;
140 }
141
throwing_subprog(struct __sk_buff * ctx)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_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region")
reject_subprog_with_rcu_read_lock(void * ctx)151 int reject_subprog_with_rcu_read_lock(void *ctx)
152 {
153 bpf_rcu_read_lock();
154 return throwing_subprog(ctx);
155 }
156
rbless(struct bpf_rb_node * n1,const struct bpf_rb_node * n2)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")
reject_with_rbtree_add_throw(void * ctx)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 bpf_spin_unlock(&lock);
175 return 0;
176 }
177
178 SEC("?tc")
179 __failure __msg("Unreleased reference")
reject_with_reference(void * ctx)180 int reject_with_reference(void *ctx)
181 {
182 struct foo *f;
183
184 f = bpf_obj_new(typeof(*f));
185 if (!f)
186 return 0;
187 bpf_throw(0);
188 return 0;
189 }
190
subprog_ref(struct __sk_buff * ctx)191 __noinline static int subprog_ref(struct __sk_buff *ctx)
192 {
193 struct foo *f;
194
195 f = bpf_obj_new(typeof(*f));
196 if (!f)
197 return 0;
198 bpf_throw(0);
199 return 0;
200 }
201
subprog_cb_ref(u32 i,void * ctx)202 __noinline static int subprog_cb_ref(u32 i, void *ctx)
203 {
204 bpf_throw(0);
205 return 0;
206 }
207
208 SEC("?tc")
209 __failure __msg("Unreleased reference")
reject_with_cb_reference(void * ctx)210 int reject_with_cb_reference(void *ctx)
211 {
212 struct foo *f;
213
214 f = bpf_obj_new(typeof(*f));
215 if (!f)
216 return 0;
217 bpf_loop(5, subprog_cb_ref, NULL, 0);
218 bpf_obj_drop(f);
219 return 0;
220 }
221
222 SEC("?tc")
223 __failure __msg("cannot be called from callback")
reject_with_cb(void * ctx)224 int reject_with_cb(void *ctx)
225 {
226 bpf_loop(5, subprog_cb_ref, NULL, 0);
227 return 0;
228 }
229
230 SEC("?tc")
231 __failure __msg("Unreleased reference")
reject_with_subprog_reference(void * ctx)232 int reject_with_subprog_reference(void *ctx)
233 {
234 return subprog_ref(ctx) + 1;
235 }
236
throwing_exception_cb(u64 c)237 __noinline int throwing_exception_cb(u64 c)
238 {
239 bpf_throw(0);
240 return c;
241 }
242
exception_cb1(u64 c)243 __noinline int exception_cb1(u64 c)
244 {
245 return c;
246 }
247
exception_cb2(u64 c)248 __noinline int exception_cb2(u64 c)
249 {
250 return c;
251 }
252
static_func(struct __sk_buff * ctx)253 static __noinline int static_func(struct __sk_buff *ctx)
254 {
255 return exception_cb1(ctx->tstamp);
256 }
257
global_func(struct __sk_buff * ctx)258 __noinline int global_func(struct __sk_buff *ctx)
259 {
260 return exception_cb1(ctx->tstamp);
261 }
262
263 SEC("?tc")
__exception_cb(throwing_exception_cb)264 __exception_cb(throwing_exception_cb)
265 __failure __msg("cannot be called from callback subprog")
266 int reject_throwing_exception_cb(struct __sk_buff *ctx)
267 {
268 return 0;
269 }
270
271 SEC("?tc")
__exception_cb(exception_cb1)272 __exception_cb(exception_cb1)
273 __failure __msg("cannot call exception cb directly")
274 int reject_exception_cb_call_global_func(struct __sk_buff *ctx)
275 {
276 return global_func(ctx);
277 }
278
279 SEC("?tc")
__exception_cb(exception_cb1)280 __exception_cb(exception_cb1)
281 __failure __msg("cannot call exception cb directly")
282 int reject_exception_cb_call_static_func(struct __sk_buff *ctx)
283 {
284 return static_func(ctx);
285 }
286
287 SEC("?tc")
__exception_cb(exception_cb1)288 __exception_cb(exception_cb1)
289 __exception_cb(exception_cb2)
290 __failure __msg("multiple exception callback tags for main subprog")
291 int reject_multiple_exception_cb(struct __sk_buff *ctx)
292 {
293 bpf_throw(0);
294 return 16;
295 }
296
exception_cb_bad_ret(u64 c)297 __noinline int exception_cb_bad_ret(u64 c)
298 {
299 return c;
300 }
301
302 SEC("?fentry/bpf_check")
__exception_cb(exception_cb_bad_ret)303 __exception_cb(exception_cb_bad_ret)
304 __failure __msg("At program exit the register R0 has unknown scalar value should")
305 int reject_set_exception_cb_bad_ret1(void *ctx)
306 {
307 return 0;
308 }
309
310 SEC("?fentry/bpf_check")
311 __failure __msg("At program exit the register R1 has smin=64 smax=64 should")
reject_set_exception_cb_bad_ret2(void * ctx)312 int reject_set_exception_cb_bad_ret2(void *ctx)
313 {
314 bpf_throw(64);
315 return 0;
316 }
317
loop_cb1(u32 index,int * ctx)318 __noinline static int loop_cb1(u32 index, int *ctx)
319 {
320 bpf_throw(0);
321 return 0;
322 }
323
loop_cb2(u32 index,int * ctx)324 __noinline static int loop_cb2(u32 index, int *ctx)
325 {
326 bpf_throw(0);
327 return 0;
328 }
329
330 SEC("?tc")
331 __failure __msg("cannot be called from callback")
reject_exception_throw_cb(struct __sk_buff * ctx)332 int reject_exception_throw_cb(struct __sk_buff *ctx)
333 {
334 bpf_loop(5, loop_cb1, NULL, 0);
335 return 0;
336 }
337
338 SEC("?tc")
339 __failure __msg("cannot be called from callback")
reject_exception_throw_cb_diff(struct __sk_buff * ctx)340 int reject_exception_throw_cb_diff(struct __sk_buff *ctx)
341 {
342 if (ctx->protocol)
343 bpf_loop(5, loop_cb1, NULL, 0);
344 else
345 bpf_loop(5, loop_cb2, NULL, 0);
346 return 0;
347 }
348
349 char _license[] SEC("license") = "GPL";
350