xref: /linux/tools/testing/selftests/bpf/progs/test_spin_lock_fail.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1c48748aeSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
2c48748aeSKumar Kartikeya Dwivedi #include <vmlinux.h>
3c48748aeSKumar Kartikeya Dwivedi #include <bpf/bpf_tracing.h>
4c48748aeSKumar Kartikeya Dwivedi #include <bpf/bpf_helpers.h>
5c48748aeSKumar Kartikeya Dwivedi #include "bpf_experimental.h"
6c48748aeSKumar Kartikeya Dwivedi 
7c48748aeSKumar Kartikeya Dwivedi struct foo {
8c48748aeSKumar Kartikeya Dwivedi 	struct bpf_spin_lock lock;
9c48748aeSKumar Kartikeya Dwivedi 	int data;
10c48748aeSKumar Kartikeya Dwivedi };
11c48748aeSKumar Kartikeya Dwivedi 
12c48748aeSKumar Kartikeya Dwivedi struct array_map {
13c48748aeSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_ARRAY);
14c48748aeSKumar Kartikeya Dwivedi 	__type(key, int);
15c48748aeSKumar Kartikeya Dwivedi 	__type(value, struct foo);
16c48748aeSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
17c48748aeSKumar Kartikeya Dwivedi } array_map SEC(".maps");
18c48748aeSKumar Kartikeya Dwivedi 
19c48748aeSKumar Kartikeya Dwivedi struct {
20c48748aeSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
21c48748aeSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
22c48748aeSKumar Kartikeya Dwivedi 	__type(key, int);
23c48748aeSKumar Kartikeya Dwivedi 	__type(value, int);
24c48748aeSKumar Kartikeya Dwivedi 	__array(values, struct array_map);
25c48748aeSKumar Kartikeya Dwivedi } map_of_maps SEC(".maps") = {
26c48748aeSKumar Kartikeya Dwivedi 	.values = {
27c48748aeSKumar Kartikeya Dwivedi 		[0] = &array_map,
28c48748aeSKumar Kartikeya Dwivedi 	},
29c48748aeSKumar Kartikeya Dwivedi };
30c48748aeSKumar Kartikeya Dwivedi 
31c48748aeSKumar Kartikeya Dwivedi SEC(".data.A") struct bpf_spin_lock lockA;
32c48748aeSKumar Kartikeya Dwivedi SEC(".data.B") struct bpf_spin_lock lockB;
33c48748aeSKumar Kartikeya Dwivedi 
34c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_kptr_preserve(void * ctx)35c48748aeSKumar Kartikeya Dwivedi int lock_id_kptr_preserve(void *ctx)
36c48748aeSKumar Kartikeya Dwivedi {
37c48748aeSKumar Kartikeya Dwivedi 	struct foo *f;
38c48748aeSKumar Kartikeya Dwivedi 
39c48748aeSKumar Kartikeya Dwivedi 	f = bpf_obj_new(typeof(*f));
40c48748aeSKumar Kartikeya Dwivedi 	if (!f)
41c48748aeSKumar Kartikeya Dwivedi 		return 0;
42c48748aeSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(f);
43c48748aeSKumar Kartikeya Dwivedi 	return 0;
44c48748aeSKumar Kartikeya Dwivedi }
45c48748aeSKumar Kartikeya Dwivedi 
46c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_global_zero(void * ctx)47c48748aeSKumar Kartikeya Dwivedi int lock_id_global_zero(void *ctx)
48c48748aeSKumar Kartikeya Dwivedi {
49c48748aeSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(&lockA);
50c48748aeSKumar Kartikeya Dwivedi 	return 0;
51c48748aeSKumar Kartikeya Dwivedi }
52c48748aeSKumar Kartikeya Dwivedi 
53c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_mapval_preserve(void * ctx)54c48748aeSKumar Kartikeya Dwivedi int lock_id_mapval_preserve(void *ctx)
55c48748aeSKumar Kartikeya Dwivedi {
56c48748aeSKumar Kartikeya Dwivedi 	struct foo *f;
57c48748aeSKumar Kartikeya Dwivedi 	int key = 0;
58c48748aeSKumar Kartikeya Dwivedi 
59c48748aeSKumar Kartikeya Dwivedi 	f = bpf_map_lookup_elem(&array_map, &key);
60c48748aeSKumar Kartikeya Dwivedi 	if (!f)
61c48748aeSKumar Kartikeya Dwivedi 		return 0;
62c48748aeSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(f);
63c48748aeSKumar Kartikeya Dwivedi 	return 0;
64c48748aeSKumar Kartikeya Dwivedi }
65c48748aeSKumar Kartikeya Dwivedi 
66c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_innermapval_preserve(void * ctx)67c48748aeSKumar Kartikeya Dwivedi int lock_id_innermapval_preserve(void *ctx)
68c48748aeSKumar Kartikeya Dwivedi {
69c48748aeSKumar Kartikeya Dwivedi 	struct foo *f;
70c48748aeSKumar Kartikeya Dwivedi 	int key = 0;
71c48748aeSKumar Kartikeya Dwivedi 	void *map;
72c48748aeSKumar Kartikeya Dwivedi 
73c48748aeSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_of_maps, &key);
74c48748aeSKumar Kartikeya Dwivedi 	if (!map)
75c48748aeSKumar Kartikeya Dwivedi 		return 0;
76c48748aeSKumar Kartikeya Dwivedi 	f = bpf_map_lookup_elem(map, &key);
77c48748aeSKumar Kartikeya Dwivedi 	if (!f)
78c48748aeSKumar Kartikeya Dwivedi 		return 0;
79c48748aeSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(f);
80c48748aeSKumar Kartikeya Dwivedi 	return 0;
81c48748aeSKumar Kartikeya Dwivedi }
82c48748aeSKumar Kartikeya Dwivedi 
83c48748aeSKumar Kartikeya Dwivedi #define CHECK(test, A, B)                                      \
84c48748aeSKumar Kartikeya Dwivedi 	SEC("?tc")                                             \
85c48748aeSKumar Kartikeya Dwivedi 	int lock_id_mismatch_##test(void *ctx)                 \
86c48748aeSKumar Kartikeya Dwivedi 	{                                                      \
87c48748aeSKumar Kartikeya Dwivedi 		struct foo *f1, *f2, *v, *iv;                  \
88c48748aeSKumar Kartikeya Dwivedi 		int key = 0;                                   \
89c48748aeSKumar Kartikeya Dwivedi 		void *map;                                     \
90c48748aeSKumar Kartikeya Dwivedi                                                                \
91c48748aeSKumar Kartikeya Dwivedi 		map = bpf_map_lookup_elem(&map_of_maps, &key); \
92c48748aeSKumar Kartikeya Dwivedi 		if (!map)                                      \
93c48748aeSKumar Kartikeya Dwivedi 			return 0;                              \
94c48748aeSKumar Kartikeya Dwivedi 		iv = bpf_map_lookup_elem(map, &key);           \
95c48748aeSKumar Kartikeya Dwivedi 		if (!iv)                                       \
96c48748aeSKumar Kartikeya Dwivedi 			return 0;                              \
97c48748aeSKumar Kartikeya Dwivedi 		v = bpf_map_lookup_elem(&array_map, &key);     \
98c48748aeSKumar Kartikeya Dwivedi 		if (!v)                                        \
99c48748aeSKumar Kartikeya Dwivedi 			return 0;                              \
100c48748aeSKumar Kartikeya Dwivedi 		f1 = bpf_obj_new(typeof(*f1));                 \
101c48748aeSKumar Kartikeya Dwivedi 		if (!f1)                                       \
102c48748aeSKumar Kartikeya Dwivedi 			return 0;                              \
103c48748aeSKumar Kartikeya Dwivedi 		f2 = bpf_obj_new(typeof(*f2));                 \
104c48748aeSKumar Kartikeya Dwivedi 		if (!f2) {                                     \
105c48748aeSKumar Kartikeya Dwivedi 			bpf_obj_drop(f1);                      \
106c48748aeSKumar Kartikeya Dwivedi 			return 0;                              \
107c48748aeSKumar Kartikeya Dwivedi 		}                                              \
108c48748aeSKumar Kartikeya Dwivedi 		bpf_spin_lock(A);                              \
109c48748aeSKumar Kartikeya Dwivedi 		bpf_spin_unlock(B);                            \
110c48748aeSKumar Kartikeya Dwivedi 		return 0;                                      \
111c48748aeSKumar Kartikeya Dwivedi 	}
112c48748aeSKumar Kartikeya Dwivedi 
113c48748aeSKumar Kartikeya Dwivedi CHECK(kptr_kptr, &f1->lock, &f2->lock);
114c48748aeSKumar Kartikeya Dwivedi CHECK(kptr_global, &f1->lock, &lockA);
115c48748aeSKumar Kartikeya Dwivedi CHECK(kptr_mapval, &f1->lock, &v->lock);
116c48748aeSKumar Kartikeya Dwivedi CHECK(kptr_innermapval, &f1->lock, &iv->lock);
117c48748aeSKumar Kartikeya Dwivedi 
118c48748aeSKumar Kartikeya Dwivedi CHECK(global_global, &lockA, &lockB);
119c48748aeSKumar Kartikeya Dwivedi CHECK(global_kptr, &lockA, &f1->lock);
120c48748aeSKumar Kartikeya Dwivedi CHECK(global_mapval, &lockA, &v->lock);
121c48748aeSKumar Kartikeya Dwivedi CHECK(global_innermapval, &lockA, &iv->lock);
122c48748aeSKumar Kartikeya Dwivedi 
123c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_mismatch_mapval_mapval(void * ctx)124c48748aeSKumar Kartikeya Dwivedi int lock_id_mismatch_mapval_mapval(void *ctx)
125c48748aeSKumar Kartikeya Dwivedi {
126c48748aeSKumar Kartikeya Dwivedi 	struct foo *f1, *f2;
127c48748aeSKumar Kartikeya Dwivedi 	int key = 0;
128c48748aeSKumar Kartikeya Dwivedi 
129c48748aeSKumar Kartikeya Dwivedi 	f1 = bpf_map_lookup_elem(&array_map, &key);
130c48748aeSKumar Kartikeya Dwivedi 	if (!f1)
131c48748aeSKumar Kartikeya Dwivedi 		return 0;
132c48748aeSKumar Kartikeya Dwivedi 	f2 = bpf_map_lookup_elem(&array_map, &key);
133c48748aeSKumar Kartikeya Dwivedi 	if (!f2)
134c48748aeSKumar Kartikeya Dwivedi 		return 0;
135c48748aeSKumar Kartikeya Dwivedi 
136c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_lock(&f1->lock);
137c48748aeSKumar Kartikeya Dwivedi 	f1->data = 42;
138c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&f2->lock);
139c48748aeSKumar Kartikeya Dwivedi 
140c48748aeSKumar Kartikeya Dwivedi 	return 0;
141c48748aeSKumar Kartikeya Dwivedi }
142c48748aeSKumar Kartikeya Dwivedi 
143c48748aeSKumar Kartikeya Dwivedi CHECK(mapval_kptr, &v->lock, &f1->lock);
144c48748aeSKumar Kartikeya Dwivedi CHECK(mapval_global, &v->lock, &lockB);
145c48748aeSKumar Kartikeya Dwivedi CHECK(mapval_innermapval, &v->lock, &iv->lock);
146c48748aeSKumar Kartikeya Dwivedi 
147c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_mismatch_innermapval_innermapval1(void * ctx)148c48748aeSKumar Kartikeya Dwivedi int lock_id_mismatch_innermapval_innermapval1(void *ctx)
149c48748aeSKumar Kartikeya Dwivedi {
150c48748aeSKumar Kartikeya Dwivedi 	struct foo *f1, *f2;
151c48748aeSKumar Kartikeya Dwivedi 	int key = 0;
152c48748aeSKumar Kartikeya Dwivedi 	void *map;
153c48748aeSKumar Kartikeya Dwivedi 
154c48748aeSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_of_maps, &key);
155c48748aeSKumar Kartikeya Dwivedi 	if (!map)
156c48748aeSKumar Kartikeya Dwivedi 		return 0;
157c48748aeSKumar Kartikeya Dwivedi 	f1 = bpf_map_lookup_elem(map, &key);
158c48748aeSKumar Kartikeya Dwivedi 	if (!f1)
159c48748aeSKumar Kartikeya Dwivedi 		return 0;
160c48748aeSKumar Kartikeya Dwivedi 	f2 = bpf_map_lookup_elem(map, &key);
161c48748aeSKumar Kartikeya Dwivedi 	if (!f2)
162c48748aeSKumar Kartikeya Dwivedi 		return 0;
163c48748aeSKumar Kartikeya Dwivedi 
164c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_lock(&f1->lock);
165c48748aeSKumar Kartikeya Dwivedi 	f1->data = 42;
166c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&f2->lock);
167c48748aeSKumar Kartikeya Dwivedi 
168c48748aeSKumar Kartikeya Dwivedi 	return 0;
169c48748aeSKumar Kartikeya Dwivedi }
170c48748aeSKumar Kartikeya Dwivedi 
171c48748aeSKumar Kartikeya Dwivedi SEC("?tc")
lock_id_mismatch_innermapval_innermapval2(void * ctx)172c48748aeSKumar Kartikeya Dwivedi int lock_id_mismatch_innermapval_innermapval2(void *ctx)
173c48748aeSKumar Kartikeya Dwivedi {
174c48748aeSKumar Kartikeya Dwivedi 	struct foo *f1, *f2;
175c48748aeSKumar Kartikeya Dwivedi 	int key = 0;
176c48748aeSKumar Kartikeya Dwivedi 	void *map;
177c48748aeSKumar Kartikeya Dwivedi 
178c48748aeSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_of_maps, &key);
179c48748aeSKumar Kartikeya Dwivedi 	if (!map)
180c48748aeSKumar Kartikeya Dwivedi 		return 0;
181c48748aeSKumar Kartikeya Dwivedi 	f1 = bpf_map_lookup_elem(map, &key);
182c48748aeSKumar Kartikeya Dwivedi 	if (!f1)
183c48748aeSKumar Kartikeya Dwivedi 		return 0;
184c48748aeSKumar Kartikeya Dwivedi 	map = bpf_map_lookup_elem(&map_of_maps, &key);
185c48748aeSKumar Kartikeya Dwivedi 	if (!map)
186c48748aeSKumar Kartikeya Dwivedi 		return 0;
187c48748aeSKumar Kartikeya Dwivedi 	f2 = bpf_map_lookup_elem(map, &key);
188c48748aeSKumar Kartikeya Dwivedi 	if (!f2)
189c48748aeSKumar Kartikeya Dwivedi 		return 0;
190c48748aeSKumar Kartikeya Dwivedi 
191c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_lock(&f1->lock);
192c48748aeSKumar Kartikeya Dwivedi 	f1->data = 42;
193c48748aeSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&f2->lock);
194c48748aeSKumar Kartikeya Dwivedi 
195c48748aeSKumar Kartikeya Dwivedi 	return 0;
196c48748aeSKumar Kartikeya Dwivedi }
197c48748aeSKumar Kartikeya Dwivedi 
198c48748aeSKumar Kartikeya Dwivedi CHECK(innermapval_kptr, &iv->lock, &f1->lock);
199c48748aeSKumar Kartikeya Dwivedi CHECK(innermapval_global, &iv->lock, &lockA);
200c48748aeSKumar Kartikeya Dwivedi CHECK(innermapval_mapval, &iv->lock, &v->lock);
201c48748aeSKumar Kartikeya Dwivedi 
202c48748aeSKumar Kartikeya Dwivedi #undef CHECK
203c48748aeSKumar Kartikeya Dwivedi 
204*e8699c4fSKumar Kartikeya Dwivedi __noinline
global_subprog(struct __sk_buff * ctx)205*e8699c4fSKumar Kartikeya Dwivedi int global_subprog(struct __sk_buff *ctx)
206*e8699c4fSKumar Kartikeya Dwivedi {
207*e8699c4fSKumar Kartikeya Dwivedi 	volatile int ret = 0;
208*e8699c4fSKumar Kartikeya Dwivedi 
209*e8699c4fSKumar Kartikeya Dwivedi 	if (ctx->protocol)
210*e8699c4fSKumar Kartikeya Dwivedi 		ret += ctx->protocol;
211*e8699c4fSKumar Kartikeya Dwivedi 	return ret + ctx->mark;
212*e8699c4fSKumar Kartikeya Dwivedi }
213*e8699c4fSKumar Kartikeya Dwivedi 
214*e8699c4fSKumar Kartikeya Dwivedi __noinline
static_subprog_call_global(struct __sk_buff * ctx)215*e8699c4fSKumar Kartikeya Dwivedi static int static_subprog_call_global(struct __sk_buff *ctx)
216*e8699c4fSKumar Kartikeya Dwivedi {
217*e8699c4fSKumar Kartikeya Dwivedi 	volatile int ret = 0;
218*e8699c4fSKumar Kartikeya Dwivedi 
219*e8699c4fSKumar Kartikeya Dwivedi 	if (ctx->protocol)
220*e8699c4fSKumar Kartikeya Dwivedi 		return ret;
221*e8699c4fSKumar Kartikeya Dwivedi 	return ret + ctx->len + global_subprog(ctx);
222*e8699c4fSKumar Kartikeya Dwivedi }
223*e8699c4fSKumar Kartikeya Dwivedi 
224*e8699c4fSKumar Kartikeya Dwivedi SEC("?tc")
lock_global_subprog_call1(struct __sk_buff * ctx)225*e8699c4fSKumar Kartikeya Dwivedi int lock_global_subprog_call1(struct __sk_buff *ctx)
226*e8699c4fSKumar Kartikeya Dwivedi {
227*e8699c4fSKumar Kartikeya Dwivedi 	int ret = 0;
228*e8699c4fSKumar Kartikeya Dwivedi 
229*e8699c4fSKumar Kartikeya Dwivedi 	bpf_spin_lock(&lockA);
230*e8699c4fSKumar Kartikeya Dwivedi 	if (ctx->mark == 42)
231*e8699c4fSKumar Kartikeya Dwivedi 		ret = global_subprog(ctx);
232*e8699c4fSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&lockA);
233*e8699c4fSKumar Kartikeya Dwivedi 	return ret;
234*e8699c4fSKumar Kartikeya Dwivedi }
235*e8699c4fSKumar Kartikeya Dwivedi 
236*e8699c4fSKumar Kartikeya Dwivedi SEC("?tc")
lock_global_subprog_call2(struct __sk_buff * ctx)237*e8699c4fSKumar Kartikeya Dwivedi int lock_global_subprog_call2(struct __sk_buff *ctx)
238*e8699c4fSKumar Kartikeya Dwivedi {
239*e8699c4fSKumar Kartikeya Dwivedi 	int ret = 0;
240*e8699c4fSKumar Kartikeya Dwivedi 
241*e8699c4fSKumar Kartikeya Dwivedi 	bpf_spin_lock(&lockA);
242*e8699c4fSKumar Kartikeya Dwivedi 	if (ctx->mark == 42)
243*e8699c4fSKumar Kartikeya Dwivedi 		ret = static_subprog_call_global(ctx);
244*e8699c4fSKumar Kartikeya Dwivedi 	bpf_spin_unlock(&lockA);
245*e8699c4fSKumar Kartikeya Dwivedi 	return ret;
246*e8699c4fSKumar Kartikeya Dwivedi }
247*e8699c4fSKumar Kartikeya Dwivedi 
248c48748aeSKumar Kartikeya Dwivedi char _license[] SEC("license") = "GPL";
249