selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / iters_state_safety.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022 Facebook */
3
4 #include <errno.h>
5 #include <string.h>
6 #include <linux/bpf.h>
7 #include <bpf/bpf_helpers.h>
8 #include "bpf_misc.h"
9
10 char _license[] SEC("license") = "GPL";
11
12 #define ITER_HELPERS                                            \
13           __imm(bpf_iter_num_new),                              \
14           __imm(bpf_iter_num_next),                             \
15           __imm(bpf_iter_num_destroy)
16
17 SEC("?raw_tp")
18 __success
19 int force_clang_to_emit_btf_for_externs(void *ctx)
20 {
21         /* we need this as a workaround to enforce compiler emitting BTF
22          * information for bpf_iter_num_{new,next,destroy}() kfuncs,
23          * as, apparently, it doesn't emit it for symbols only referenced from
24          * assembly (or cleanup attribute, for that matter, as well)
25          */
26         bpf_repeat(0);
27
28         return 0;
29 }
30
31 SEC("?raw_tp")
32 __success __log_level(2)
33 __msg("fp-8_w=iter_num(ref_id=1,state=active,depth=0)")
34 int create_and_destroy(void *ctx)
35 {
36         struct bpf_iter_num iter;
37
38         asm volatile (
39                 /* create iterator */
40                 "r1 = %[iter];"
41                 "r2 = 0;"
42                 "r3 = 1000;"
43                 "call %[bpf_iter_num_new];"
44                 /* destroy iterator */
45                 "r1 = %[iter];"
46                 "call %[bpf_iter_num_destroy];"
47                 :
48                 : __imm_ptr(iter), ITER_HELPERS
49                 : __clobber_common
50         );
51
52         return 0;
53 }
54
55 SEC("?raw_tp")
56 __failure __msg("Unreleased reference id=1")
57 int create_and_forget_to_destroy_fail(void *ctx)
58 {
59         struct bpf_iter_num iter;
60
61         asm volatile (
62                 /* create iterator */
63                 "r1 = %[iter];"
64                 "r2 = 0;"
65                 "r3 = 1000;"
66                 "call %[bpf_iter_num_new];"
67                 :
68                 : __imm_ptr(iter), ITER_HELPERS
69                 : __clobber_common
70         );
71
72         return 0;
73 }
74
75 SEC("?raw_tp")
76 __failure __msg("expected an initialized iter_num as arg #1")
77 int destroy_without_creating_fail(void *ctx)
78 {
79         /* init with zeros to stop verifier complaining about uninit stack */
80         struct bpf_iter_num iter;
81
82         asm volatile (
83                 "r1 = %[iter];"
84                 "call %[bpf_iter_num_destroy];"
85                 :
86                 : __imm_ptr(iter), ITER_HELPERS
87                 : __clobber_common
88         );
89
90         return 0;
91 }
92
93 SEC("?raw_tp")
94 __failure __msg("expected an initialized iter_num as arg #1")
95 int compromise_iter_w_direct_write_fail(void *ctx)
96 {
97         struct bpf_iter_num iter;
98
99         asm volatile (
100                 /* create iterator */
101                 "r1 = %[iter];"
102                 "r2 = 0;"
103                 "r3 = 1000;"
104                 "call %[bpf_iter_num_new];"
105
106                 /* directly write over first half of iter state */
107                 "*(u64 *)(%[iter] + 0) = r0;"
108
109                 /* (attempt to) destroy iterator */
110                 "r1 = %[iter];"
111                 "call %[bpf_iter_num_destroy];"
112                 :
113                 : __imm_ptr(iter), ITER_HELPERS
114                 : __clobber_common
115         );
116
117         return 0;
118 }
119
120 SEC("?raw_tp")
121 __failure __msg("Unreleased reference id=1")
122 int compromise_iter_w_direct_write_and_skip_destroy_fail(void *ctx)
123 {
124         struct bpf_iter_num iter;
125
126         asm volatile (
127                 /* create iterator */
128                 "r1 = %[iter];"
129                 "r2 = 0;"
130                 "r3 = 1000;"
131                 "call %[bpf_iter_num_new];"
132
133                 /* directly write over first half of iter state */
134                 "*(u64 *)(%[iter] + 0) = r0;"
135
136                 /* don't destroy iter, leaking ref, which should fail */
137                 :
138                 : __imm_ptr(iter), ITER_HELPERS
139                 : __clobber_common
140         );
141
142         return 0;
143 }
144
145 SEC("?raw_tp")
146 __failure __msg("expected an initialized iter_num as arg #1")
147 int compromise_iter_w_helper_write_fail(void *ctx)
148 {
149         struct bpf_iter_num iter;
150
151         asm volatile (
152                 /* create iterator */
153                 "r1 = %[iter];"
154                 "r2 = 0;"
155                 "r3 = 1000;"
156                 "call %[bpf_iter_num_new];"
157
158                 /* overwrite 8th byte with bpf_probe_read_kernel() */
159                 "r1 = %[iter];"
160                 "r1 += 7;"
161                 "r2 = 1;"
162                 "r3 = 0;" /* NULL */
163                 "call %[bpf_probe_read_kernel];"
164
165                 /* (attempt to) destroy iterator */
166                 "r1 = %[iter];"
167                 "call %[bpf_iter_num_destroy];"
168                 :
169                 : __imm_ptr(iter), ITER_HELPERS, __imm(bpf_probe_read_kernel)
170                 : __clobber_common
171         );
172
173         return 0;
174 }
175
176 static __noinline void subprog_with_iter(void)
177 {
178         struct bpf_iter_num iter;
179
180         bpf_iter_num_new(&iter, 0, 1);
181
182         return;
183 }
184
185 SEC("?raw_tp")
186 __failure
187 /* ensure there was a call to subprog, which might happen without __noinline */
188 __msg("returning from callee:")
189 __msg("Unreleased reference id=1")
190 int leak_iter_from_subprog_fail(void *ctx)
191 {
192         subprog_with_iter();
193
194         return 0;
195 }
196
197 SEC("?raw_tp")
198 __success __log_level(2)
199 __msg("fp-8_w=iter_num(ref_id=1,state=active,depth=0)")
200 int valid_stack_reuse(void *ctx)
201 {
202         struct bpf_iter_num iter;
203
204         asm volatile (
205                 /* create iterator */
206                 "r1 = %[iter];"
207                 "r2 = 0;"
208                 "r3 = 1000;"
209                 "call %[bpf_iter_num_new];"
210                 /* destroy iterator */
211                 "r1 = %[iter];"
212                 "call %[bpf_iter_num_destroy];"
213
214                 /* now reuse same stack slots */
215
216                 /* create iterator */
217                 "r1 = %[iter];"
218                 "r2 = 0;"
219                 "r3 = 1000;"
220                 "call %[bpf_iter_num_new];"
221                 /* destroy iterator */
222                 "r1 = %[iter];"
223                 "call %[bpf_iter_num_destroy];"
224                 :
225                 : __imm_ptr(iter), ITER_HELPERS
226                 : __clobber_common
227         );
228
229         return 0;
230 }
231
232 SEC("?raw_tp")
233 __failure __msg("expected uninitialized iter_num as arg #1")
234 int double_create_fail(void *ctx)
235 {
236         struct bpf_iter_num iter;
237
238         asm volatile (
239                 /* create iterator */
240                 "r1 = %[iter];"
241                 "r2 = 0;"
242                 "r3 = 1000;"
243                 "call %[bpf_iter_num_new];"
244                 /* (attempt to) create iterator again */
245                 "r1 = %[iter];"
246                 "r2 = 0;"
247                 "r3 = 1000;"
248                 "call %[bpf_iter_num_new];"
249                 /* destroy iterator */
250                 "r1 = %[iter];"
251                 "call %[bpf_iter_num_destroy];"
252                 :
253                 : __imm_ptr(iter), ITER_HELPERS
254                 : __clobber_common
255         );
256
257         return 0;
258 }
259
260 SEC("?raw_tp")
261 __failure __msg("expected an initialized iter_num as arg #1")
262 int double_destroy_fail(void *ctx)
263 {
264         struct bpf_iter_num iter;
265
266         asm volatile (
267                 /* create iterator */
268                 "r1 = %[iter];"
269                 "r2 = 0;"
270                 "r3 = 1000;"
271                 "call %[bpf_iter_num_new];"
272                 /* destroy iterator */
273                 "r1 = %[iter];"
274                 "call %[bpf_iter_num_destroy];"
275                 /* (attempt to) destroy iterator again */
276                 "r1 = %[iter];"
277                 "call %[bpf_iter_num_destroy];"
278                 :
279                 : __imm_ptr(iter), ITER_HELPERS
280                 : __clobber_common
281         );
282
283         return 0;
284 }
285
286 SEC("?raw_tp")
287 __failure __msg("expected an initialized iter_num as arg #1")
288 int next_without_new_fail(void *ctx)
289 {
290         struct bpf_iter_num iter;
291
292         asm volatile (
293                 /* don't create iterator and try to iterate*/
294                 "r1 = %[iter];"
295                 "call %[bpf_iter_num_next];"
296                 /* destroy iterator */
297                 "r1 = %[iter];"
298                 "call %[bpf_iter_num_destroy];"
299                 :
300                 : __imm_ptr(iter), ITER_HELPERS
301                 : __clobber_common
302         );
303
304         return 0;
305 }
306
307 SEC("?raw_tp")
308 __failure __msg("expected an initialized iter_num as arg #1")
309 int next_after_destroy_fail(void *ctx)
310 {
311         struct bpf_iter_num iter;
312
313         asm volatile (
314                 /* create iterator */
315                 "r1 = %[iter];"
316                 "r2 = 0;"
317                 "r3 = 1000;"
318                 "call %[bpf_iter_num_new];"
319                 /* destroy iterator */
320                 "r1 = %[iter];"
321                 "call %[bpf_iter_num_destroy];"
322                 /* don't create iterator and try to iterate*/
323                 "r1 = %[iter];"
324                 "call %[bpf_iter_num_next];"
325                 :
326                 : __imm_ptr(iter), ITER_HELPERS
327                 : __clobber_common
328         );
329
330         return 0;
331 }
332
333 SEC("?raw_tp")
334 __failure __msg("invalid read from stack")
335 int __naked read_from_iter_slot_fail(void)
336 {
337         asm volatile (
338                 /* r6 points to struct bpf_iter_num on the stack */
339                 "r6 = r10;"
340                 "r6 += -24;"
341
342                 /* create iterator */
343                 "r1 = r6;"
344                 "r2 = 0;"
345                 "r3 = 1000;"
346                 "call %[bpf_iter_num_new];"
347
348                 /* attemp to leak bpf_iter_num state */
349                 "r7 = *(u64 *)(r6 + 0);"
350                 "r8 = *(u64 *)(r6 + 8);"
351
352                 /* destroy iterator */
353                 "r1 = r6;"
354                 "call %[bpf_iter_num_destroy];"
355
356                 /* leak bpf_iter_num state */
357                 "r0 = r7;"
358                 "if r7 > r8 goto +1;"
359                 "r0 = r8;"
360                 "exit;"
361                 :
362                 : ITER_HELPERS
363                 : __clobber_common, "r6", "r7", "r8"
364         );
365 }
366
367 int zero;
368
369 SEC("?raw_tp")
370 __failure
371 __flag(BPF_F_TEST_STATE_FREQ)
372 __msg("Unreleased reference")
373 int stacksafe_should_not_conflate_stack_spill_and_iter(void *ctx)
374 {
375         struct bpf_iter_num iter;
376
377         asm volatile (
378                 /* Create a fork in logic, with general setup as follows:
379                  *   - fallthrough (first) path is valid;
380                  *   - branch (second) path is invalid.
381                  * Then depending on what we do in fallthrough vs branch path,
382                  * we try to detect bugs in func_states_equal(), regsafe(),
383                  * refsafe(), stack_safe(), and similar by tricking verifier
384                  * into believing that branch state is a valid subset of
385                  * a fallthrough state. Verifier should reject overall
386                  * validation, unless there is a bug somewhere in verifier
387                  * logic.
388                  */
389                 "call %[bpf_get_prandom_u32];"
390                 "r6 = r0;"
391                 "call %[bpf_get_prandom_u32];"
392                 "r7 = r0;"
393
394                 "if r6 > r7 goto bad;" /* fork */
395
396                 /* spill r6 into stack slot of bpf_iter_num var */
397                 "*(u64 *)(%[iter] + 0) = r6;"
398
399                 "goto skip_bad;"
400
401         "bad:"
402                 /* create iterator in the same stack slot */
403                 "r1 = %[iter];"
404                 "r2 = 0;"
405                 "r3 = 1000;"
406                 "call %[bpf_iter_num_new];"
407
408                 /* but then forget about it and overwrite it back to r6 spill */
409                 "*(u64 *)(%[iter] + 0) = r6;"
410
411         "skip_bad:"
412                 "goto +0;" /* force checkpoint */
413
414                 /* corrupt stack slots, if they are really dynptr */
415                 "*(u64 *)(%[iter] + 0) = r6;"
416                 :
417                 : __imm_ptr(iter),
418                   __imm_addr(zero),
419                   __imm(bpf_get_prandom_u32),
420                   __imm(bpf_dynptr_from_mem),
421                   ITER_HELPERS
422                 : __clobber_common, "r6", "r7"
423         );
424
425         return 0;
426 }