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_experimental.h"
6
7 struct foo {
8 struct bpf_spin_lock lock;
9 int data;
10 };
11
12 struct array_map {
13 __uint(type, BPF_MAP_TYPE_ARRAY);
14 __type(key, int);
15 __type(value, struct foo);
16 __uint(max_entries, 1);
17 } array_map SEC(".maps");
18
19 struct {
20 __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
21 __uint(max_entries, 1);
22 __type(key, int);
23 __type(value, int);
24 __array(values, struct array_map);
25 } map_of_maps SEC(".maps") = {
26 .values = {
27 [0] = &array_map,
28 },
29 };
30
31 static struct bpf_spin_lock lockA SEC(".data.A");
32 static struct bpf_spin_lock lockB SEC(".data.B");
33
34 SEC("?tc")
lock_id_kptr_preserve(void * ctx)35 int lock_id_kptr_preserve(void *ctx)
36 {
37 struct foo *f;
38
39 f = bpf_obj_new(typeof(*f));
40 if (!f)
41 return 0;
42 bpf_this_cpu_ptr(f);
43 return 0;
44 }
45
46 SEC("?tc")
lock_id_global_zero(void * ctx)47 int lock_id_global_zero(void *ctx)
48 {
49 bpf_this_cpu_ptr(&lockA);
50 return 0;
51 }
52
53 SEC("?tc")
lock_id_mapval_preserve(void * ctx)54 int lock_id_mapval_preserve(void *ctx)
55 {
56 struct foo *f;
57 int key = 0;
58
59 f = bpf_map_lookup_elem(&array_map, &key);
60 if (!f)
61 return 0;
62 bpf_this_cpu_ptr(f);
63 return 0;
64 }
65
66 SEC("?tc")
lock_id_innermapval_preserve(void * ctx)67 int lock_id_innermapval_preserve(void *ctx)
68 {
69 struct foo *f;
70 int key = 0;
71 void *map;
72
73 map = bpf_map_lookup_elem(&map_of_maps, &key);
74 if (!map)
75 return 0;
76 f = bpf_map_lookup_elem(map, &key);
77 if (!f)
78 return 0;
79 bpf_this_cpu_ptr(f);
80 return 0;
81 }
82
83 #define CHECK(test, A, B) \
84 SEC("?tc") \
85 int lock_id_mismatch_##test(void *ctx) \
86 { \
87 struct foo *f1, *f2, *v, *iv; \
88 int key = 0; \
89 void *map; \
90 \
91 map = bpf_map_lookup_elem(&map_of_maps, &key); \
92 if (!map) \
93 return 0; \
94 iv = bpf_map_lookup_elem(map, &key); \
95 if (!iv) \
96 return 0; \
97 v = bpf_map_lookup_elem(&array_map, &key); \
98 if (!v) \
99 return 0; \
100 f1 = bpf_obj_new(typeof(*f1)); \
101 if (!f1) \
102 return 0; \
103 f2 = bpf_obj_new(typeof(*f2)); \
104 if (!f2) { \
105 bpf_obj_drop(f1); \
106 return 0; \
107 } \
108 bpf_spin_lock(A); \
109 bpf_spin_unlock(B); \
110 return 0; \
111 }
112
113 CHECK(kptr_kptr, &f1->lock, &f2->lock);
114 CHECK(kptr_global, &f1->lock, &lockA);
115 CHECK(kptr_mapval, &f1->lock, &v->lock);
116 CHECK(kptr_innermapval, &f1->lock, &iv->lock);
117
118 CHECK(global_global, &lockA, &lockB);
119 CHECK(global_kptr, &lockA, &f1->lock);
120 CHECK(global_mapval, &lockA, &v->lock);
121 CHECK(global_innermapval, &lockA, &iv->lock);
122
123 SEC("?tc")
lock_id_mismatch_mapval_mapval(void * ctx)124 int lock_id_mismatch_mapval_mapval(void *ctx)
125 {
126 struct foo *f1, *f2;
127 int key = 0;
128
129 f1 = bpf_map_lookup_elem(&array_map, &key);
130 if (!f1)
131 return 0;
132 f2 = bpf_map_lookup_elem(&array_map, &key);
133 if (!f2)
134 return 0;
135
136 bpf_spin_lock(&f1->lock);
137 f1->data = 42;
138 bpf_spin_unlock(&f2->lock);
139
140 return 0;
141 }
142
143 CHECK(mapval_kptr, &v->lock, &f1->lock);
144 CHECK(mapval_global, &v->lock, &lockB);
145 CHECK(mapval_innermapval, &v->lock, &iv->lock);
146
147 SEC("?tc")
lock_id_mismatch_innermapval_innermapval1(void * ctx)148 int lock_id_mismatch_innermapval_innermapval1(void *ctx)
149 {
150 struct foo *f1, *f2;
151 int key = 0;
152 void *map;
153
154 map = bpf_map_lookup_elem(&map_of_maps, &key);
155 if (!map)
156 return 0;
157 f1 = bpf_map_lookup_elem(map, &key);
158 if (!f1)
159 return 0;
160 f2 = bpf_map_lookup_elem(map, &key);
161 if (!f2)
162 return 0;
163
164 bpf_spin_lock(&f1->lock);
165 f1->data = 42;
166 bpf_spin_unlock(&f2->lock);
167
168 return 0;
169 }
170
171 SEC("?tc")
lock_id_mismatch_innermapval_innermapval2(void * ctx)172 int lock_id_mismatch_innermapval_innermapval2(void *ctx)
173 {
174 struct foo *f1, *f2;
175 int key = 0;
176 void *map;
177
178 map = bpf_map_lookup_elem(&map_of_maps, &key);
179 if (!map)
180 return 0;
181 f1 = bpf_map_lookup_elem(map, &key);
182 if (!f1)
183 return 0;
184 map = bpf_map_lookup_elem(&map_of_maps, &key);
185 if (!map)
186 return 0;
187 f2 = bpf_map_lookup_elem(map, &key);
188 if (!f2)
189 return 0;
190
191 bpf_spin_lock(&f1->lock);
192 f1->data = 42;
193 bpf_spin_unlock(&f2->lock);
194
195 return 0;
196 }
197
198 CHECK(innermapval_kptr, &iv->lock, &f1->lock);
199 CHECK(innermapval_global, &iv->lock, &lockA);
200 CHECK(innermapval_mapval, &iv->lock, &v->lock);
201
202 #undef CHECK
203
204 char _license[] SEC("license") = "GPL";
205