xref: /linux/tools/testing/selftests/bpf/progs/tailcall_fail.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
1*711df091SKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
2*711df091SKumar Kartikeya Dwivedi /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3*711df091SKumar Kartikeya Dwivedi #include <vmlinux.h>
4*711df091SKumar Kartikeya Dwivedi #include <bpf/bpf_tracing.h>
5*711df091SKumar Kartikeya Dwivedi #include <bpf/bpf_helpers.h>
6*711df091SKumar Kartikeya Dwivedi #include <bpf/bpf_core_read.h>
7*711df091SKumar Kartikeya Dwivedi 
8*711df091SKumar Kartikeya Dwivedi #include "bpf_misc.h"
9*711df091SKumar Kartikeya Dwivedi #include "bpf_experimental.h"
10*711df091SKumar Kartikeya Dwivedi 
11*711df091SKumar Kartikeya Dwivedi extern void bpf_rcu_read_lock(void) __ksym;
12*711df091SKumar Kartikeya Dwivedi extern void bpf_rcu_read_unlock(void) __ksym;
13*711df091SKumar Kartikeya Dwivedi 
14*711df091SKumar Kartikeya Dwivedi #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
15*711df091SKumar Kartikeya Dwivedi 
16*711df091SKumar Kartikeya Dwivedi private(A) struct bpf_spin_lock lock;
17*711df091SKumar Kartikeya Dwivedi 
18*711df091SKumar Kartikeya Dwivedi struct {
19*711df091SKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
20*711df091SKumar Kartikeya Dwivedi 	__uint(max_entries, 3);
21*711df091SKumar Kartikeya Dwivedi 	__uint(key_size, sizeof(__u32));
22*711df091SKumar Kartikeya Dwivedi 	__uint(value_size, sizeof(__u32));
23*711df091SKumar Kartikeya Dwivedi } jmp_table SEC(".maps");
24*711df091SKumar Kartikeya Dwivedi 
25*711df091SKumar Kartikeya Dwivedi SEC("?tc")
26*711df091SKumar Kartikeya Dwivedi __failure __msg("function calls are not allowed while holding a lock")
27*711df091SKumar Kartikeya Dwivedi int reject_tail_call_spin_lock(struct __sk_buff *ctx)
28*711df091SKumar Kartikeya Dwivedi {
29*711df091SKumar Kartikeya Dwivedi 	bpf_spin_lock(&lock);
30*711df091SKumar Kartikeya Dwivedi 	bpf_tail_call_static(ctx, &jmp_table, 0);
31*711df091SKumar Kartikeya Dwivedi 	return 0;
32*711df091SKumar Kartikeya Dwivedi }
33*711df091SKumar Kartikeya Dwivedi 
34*711df091SKumar Kartikeya Dwivedi SEC("?tc")
35*711df091SKumar Kartikeya Dwivedi __failure __msg("tail_call cannot be used inside bpf_rcu_read_lock-ed region")
36*711df091SKumar Kartikeya Dwivedi int reject_tail_call_rcu_lock(struct __sk_buff *ctx)
37*711df091SKumar Kartikeya Dwivedi {
38*711df091SKumar Kartikeya Dwivedi 	bpf_rcu_read_lock();
39*711df091SKumar Kartikeya Dwivedi 	bpf_tail_call_static(ctx, &jmp_table, 0);
40*711df091SKumar Kartikeya Dwivedi 	bpf_rcu_read_unlock();
41*711df091SKumar Kartikeya Dwivedi 	return 0;
42*711df091SKumar Kartikeya Dwivedi }
43*711df091SKumar Kartikeya Dwivedi 
44*711df091SKumar Kartikeya Dwivedi SEC("?tc")
45*711df091SKumar Kartikeya Dwivedi __failure __msg("tail_call cannot be used inside bpf_preempt_disable-ed region")
46*711df091SKumar Kartikeya Dwivedi int reject_tail_call_preempt_lock(struct __sk_buff *ctx)
47*711df091SKumar Kartikeya Dwivedi {
48*711df091SKumar Kartikeya Dwivedi 	bpf_guard_preempt();
49*711df091SKumar Kartikeya Dwivedi 	bpf_tail_call_static(ctx, &jmp_table, 0);
50*711df091SKumar Kartikeya Dwivedi 	return 0;
51*711df091SKumar Kartikeya Dwivedi }
52*711df091SKumar Kartikeya Dwivedi 
53*711df091SKumar Kartikeya Dwivedi SEC("?tc")
54*711df091SKumar Kartikeya Dwivedi __failure __msg("tail_call would lead to reference leak")
55*711df091SKumar Kartikeya Dwivedi int reject_tail_call_ref(struct __sk_buff *ctx)
56*711df091SKumar Kartikeya Dwivedi {
57*711df091SKumar Kartikeya Dwivedi 	struct foo { int i; } *p;
58*711df091SKumar Kartikeya Dwivedi 
59*711df091SKumar Kartikeya Dwivedi 	p = bpf_obj_new(typeof(*p));
60*711df091SKumar Kartikeya Dwivedi 	bpf_tail_call_static(ctx, &jmp_table, 0);
61*711df091SKumar Kartikeya Dwivedi 	return 0;
62*711df091SKumar Kartikeya Dwivedi }
63*711df091SKumar Kartikeya Dwivedi 
64*711df091SKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
65