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 | SEC(".data.A" ) struct bpf_spin_lock lockA; |
32 | SEC(".data.B" ) struct bpf_spin_lock lockB; |
33 | |
34 | SEC("?tc" ) |
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" ) |
47 | int lock_id_global_zero(void *ctx) |
48 | { |
49 | bpf_this_cpu_ptr(&lockA); |
50 | return 0; |
51 | } |
52 | |
53 | SEC("?tc" ) |
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" ) |
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" ) |
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" ) |
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" ) |
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 | __noinline |
205 | int global_subprog(struct __sk_buff *ctx) |
206 | { |
207 | volatile int ret = 0; |
208 | |
209 | if (ctx->protocol) |
210 | ret += ctx->protocol; |
211 | return ret + ctx->mark; |
212 | } |
213 | |
214 | __noinline |
215 | static int static_subprog_call_global(struct __sk_buff *ctx) |
216 | { |
217 | volatile int ret = 0; |
218 | |
219 | if (ctx->protocol) |
220 | return ret; |
221 | return ret + ctx->len + global_subprog(ctx); |
222 | } |
223 | |
224 | SEC("?tc" ) |
225 | int lock_global_subprog_call1(struct __sk_buff *ctx) |
226 | { |
227 | int ret = 0; |
228 | |
229 | bpf_spin_lock(&lockA); |
230 | if (ctx->mark == 42) |
231 | ret = global_subprog(ctx); |
232 | bpf_spin_unlock(&lockA); |
233 | return ret; |
234 | } |
235 | |
236 | SEC("?tc" ) |
237 | int lock_global_subprog_call2(struct __sk_buff *ctx) |
238 | { |
239 | int ret = 0; |
240 | |
241 | bpf_spin_lock(&lockA); |
242 | if (ctx->mark == 42) |
243 | ret = static_subprog_call_global(ctx); |
244 | bpf_spin_unlock(&lockA); |
245 | return ret; |
246 | } |
247 | |
248 | char _license[] SEC("license" ) = "GPL" ; |
249 | |