1// SPDX-License-Identifier: GPL-2.0
2#include <vmlinux.h>
3#include <bpf/bpf_helpers.h>
4#include <bpf/bpf_tracing.h>
5#include "bpf_misc.h"
6#include "bpf_experimental.h"
7
8SEC("?tc")
9__failure __msg("1 bpf_preempt_enable is missing")
10int preempt_lock_missing_1(struct __sk_buff *ctx)
11{
12	bpf_preempt_disable();
13	return 0;
14}
15
16SEC("?tc")
17__failure __msg("2 bpf_preempt_enable(s) are missing")
18int preempt_lock_missing_2(struct __sk_buff *ctx)
19{
20	bpf_preempt_disable();
21	bpf_preempt_disable();
22	return 0;
23}
24
25SEC("?tc")
26__failure __msg("3 bpf_preempt_enable(s) are missing")
27int preempt_lock_missing_3(struct __sk_buff *ctx)
28{
29	bpf_preempt_disable();
30	bpf_preempt_disable();
31	bpf_preempt_disable();
32	return 0;
33}
34
35SEC("?tc")
36__failure __msg("1 bpf_preempt_enable is missing")
37int preempt_lock_missing_3_minus_2(struct __sk_buff *ctx)
38{
39	bpf_preempt_disable();
40	bpf_preempt_disable();
41	bpf_preempt_disable();
42	bpf_preempt_enable();
43	bpf_preempt_enable();
44	return 0;
45}
46
47static __noinline void preempt_disable(void)
48{
49	bpf_preempt_disable();
50}
51
52static __noinline void preempt_enable(void)
53{
54	bpf_preempt_enable();
55}
56
57SEC("?tc")
58__failure __msg("1 bpf_preempt_enable is missing")
59int preempt_lock_missing_1_subprog(struct __sk_buff *ctx)
60{
61	preempt_disable();
62	return 0;
63}
64
65SEC("?tc")
66__failure __msg("2 bpf_preempt_enable(s) are missing")
67int preempt_lock_missing_2_subprog(struct __sk_buff *ctx)
68{
69	preempt_disable();
70	preempt_disable();
71	return 0;
72}
73
74SEC("?tc")
75__failure __msg("1 bpf_preempt_enable is missing")
76int preempt_lock_missing_2_minus_1_subprog(struct __sk_buff *ctx)
77{
78	preempt_disable();
79	preempt_disable();
80	preempt_enable();
81	return 0;
82}
83
84static __noinline void preempt_balance_subprog(void)
85{
86	preempt_disable();
87	preempt_enable();
88}
89
90SEC("?tc")
91__success int preempt_balance(struct __sk_buff *ctx)
92{
93	bpf_guard_preempt();
94	return 0;
95}
96
97SEC("?tc")
98__success int preempt_balance_subprog_test(struct __sk_buff *ctx)
99{
100	preempt_balance_subprog();
101	return 0;
102}
103
104SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
105__failure __msg("sleepable helper bpf_copy_from_user#")
106int preempt_sleepable_helper(void *ctx)
107{
108	u32 data;
109
110	bpf_preempt_disable();
111	bpf_copy_from_user(&data, sizeof(data), NULL);
112	bpf_preempt_enable();
113	return 0;
114}
115
116int __noinline preempt_global_subprog(void)
117{
118	preempt_balance_subprog();
119	return 0;
120}
121
122SEC("?tc")
123__failure __msg("global function calls are not allowed with preemption disabled")
124int preempt_global_subprog_test(struct __sk_buff *ctx)
125{
126	preempt_disable();
127	preempt_global_subprog();
128	preempt_enable();
129	return 0;
130}
131
132char _license[] SEC("license") = "GPL";
133