File Index
Files and directories
Sign in
FILE

exceptions_fail.c

File preview with syntax highlighting.

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