selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / verifier_subreg.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Converted from tools/testing/selftests/bpf/verifier/subreg.c */
3
4 #include <linux/bpf.h>
5 #include <bpf/bpf_helpers.h>
6 #include "bpf_misc.h"
7
8 /* This file contains sub-register zero extension checks for insns defining
9  * sub-registers, meaning:
10  *   - All insns under BPF_ALU class. Their BPF_ALU32 variants or narrow width
11  *     forms (BPF_END) could define sub-registers.
12  *   - Narrow direct loads, BPF_B/H/W | BPF_LDX.
13  *   - BPF_LD is not exposed to JIT back-ends, so no need for testing.
14  *
15  * "get_prandom_u32" is used to initialize low 32-bit of some registers to
16  * prevent potential optimizations done by verifier or JIT back-ends which could
17  * optimize register back into constant when range info shows one register is a
18  * constant.
19  */
20
21 SEC("socket")
22 __description("add32 reg zero extend check")
23 __success __success_unpriv __retval(0)
24 __naked void add32_reg_zero_extend_check(void)
25 {
26         asm volatile ("                                 \
27         call %[bpf_get_prandom_u32];                    \
28         r1 = r0;                                        \
29         r0 = 0x100000000 ll;                            \
30         w0 += w1;                                       \
31         r0 >>= 32;                                      \
32         exit;                                           \
33 "       :
34         : __imm(bpf_get_prandom_u32)
35         : __clobber_all);
36 }
37
38 SEC("socket")
39 __description("add32 imm zero extend check")
40 __success __success_unpriv __retval(0)
41 __naked void add32_imm_zero_extend_check(void)
42 {
43         asm volatile ("                                 \
44         call %[bpf_get_prandom_u32];                    \
45         r1 = 0x1000000000 ll;                           \
46         r0 |= r1;                                       \
47         /* An insn could have no effect on the low 32-bit, for example:\
48          *   a = a + 0                                  \
49          *   a = a | 0                                  \
50          *   a = a & -1                                 \
51          * But, they should still zero high 32-bit.     \
52          */                                             \
53         w0 += 0;                                        \
54         r0 >>= 32;                                      \
55         r6 = r0;                                        \
56         call %[bpf_get_prandom_u32];                    \
57         r1 = 0x1000000000 ll;                           \
58         r0 |= r1;                                       \
59         w0 += -2;                                       \
60         r0 >>= 32;                                      \
61         r0 |= r6;                                       \
62         exit;                                           \
63 "       :
64         : __imm(bpf_get_prandom_u32)
65         : __clobber_all);
66 }
67
68 SEC("socket")
69 __description("sub32 reg zero extend check")
70 __success __success_unpriv __retval(0)
71 __naked void sub32_reg_zero_extend_check(void)
72 {
73         asm volatile ("                                 \
74         call %[bpf_get_prandom_u32];                    \
75         r1 = r0;                                        \
76         r0 = 0x1ffffffff ll;                            \
77         w0 -= w1;                                       \
78         r0 >>= 32;                                      \
79         exit;                                           \
80 "       :
81         : __imm(bpf_get_prandom_u32)
82         : __clobber_all);
83 }
84
85 SEC("socket")
86 __description("sub32 imm zero extend check")
87 __success __success_unpriv __retval(0)
88 __naked void sub32_imm_zero_extend_check(void)
89 {
90         asm volatile ("                                 \
91         call %[bpf_get_prandom_u32];                    \
92         r1 = 0x1000000000 ll;                           \
93         r0 |= r1;                                       \
94         w0 -= 0;                                        \
95         r0 >>= 32;                                      \
96         r6 = r0;                                        \
97         call %[bpf_get_prandom_u32];                    \
98         r1 = 0x1000000000 ll;                           \
99         r0 |= r1;                                       \
100         w0 -= 1;                                        \
101         r0 >>= 32;                                      \
102         r0 |= r6;                                       \
103         exit;                                           \
104 "       :
105         : __imm(bpf_get_prandom_u32)
106         : __clobber_all);
107 }
108
109 SEC("socket")
110 __description("mul32 reg zero extend check")
111 __success __success_unpriv __retval(0)
112 __naked void mul32_reg_zero_extend_check(void)
113 {
114         asm volatile ("                                 \
115         call %[bpf_get_prandom_u32];                    \
116         r1 = r0;                                        \
117         r0 = 0x100000001 ll;                            \
118         w0 *= w1;                                       \
119         r0 >>= 32;                                      \
120         exit;                                           \
121 "       :
122         : __imm(bpf_get_prandom_u32)
123         : __clobber_all);
124 }
125
126 SEC("socket")
127 __description("mul32 imm zero extend check")
128 __success __success_unpriv __retval(0)
129 __naked void mul32_imm_zero_extend_check(void)
130 {
131         asm volatile ("                                 \
132         call %[bpf_get_prandom_u32];                    \
133         r1 = 0x1000000000 ll;                           \
134         r0 |= r1;                                       \
135         w0 *= 1;                                        \
136         r0 >>= 32;                                      \
137         r6 = r0;                                        \
138         call %[bpf_get_prandom_u32];                    \
139         r1 = 0x1000000000 ll;                           \
140         r0 |= r1;                                       \
141         w0 *= -1;                                       \
142         r0 >>= 32;                                      \
143         r0 |= r6;                                       \
144         exit;                                           \
145 "       :
146         : __imm(bpf_get_prandom_u32)
147         : __clobber_all);
148 }
149
150 SEC("socket")
151 __description("div32 reg zero extend check")
152 __success __success_unpriv __retval(0)
153 __naked void div32_reg_zero_extend_check(void)
154 {
155         asm volatile ("                                 \
156         call %[bpf_get_prandom_u32];                    \
157         r1 = r0;                                        \
158         r0 = -1;                                        \
159         w0 /= w1;                                       \
160         r0 >>= 32;                                      \
161         exit;                                           \
162 "       :
163         : __imm(bpf_get_prandom_u32)
164         : __clobber_all);
165 }
166
167 SEC("socket")
168 __description("div32 imm zero extend check")
169 __success __success_unpriv __retval(0)
170 __naked void div32_imm_zero_extend_check(void)
171 {
172         asm volatile ("                                 \
173         call %[bpf_get_prandom_u32];                    \
174         r1 = 0x1000000000 ll;                           \
175         r0 |= r1;                                       \
176         w0 /= 1;                                        \
177         r0 >>= 32;                                      \
178         r6 = r0;                                        \
179         call %[bpf_get_prandom_u32];                    \
180         r1 = 0x1000000000 ll;                           \
181         r0 |= r1;                                       \
182         w0 /= 2;                                        \
183         r0 >>= 32;                                      \
184         r0 |= r6;                                       \
185         exit;                                           \
186 "       :
187         : __imm(bpf_get_prandom_u32)
188         : __clobber_all);
189 }
190
191 SEC("socket")
192 __description("or32 reg zero extend check")
193 __success __success_unpriv __retval(0)
194 __naked void or32_reg_zero_extend_check(void)
195 {
196         asm volatile ("                                 \
197         call %[bpf_get_prandom_u32];                    \
198         r1 = r0;                                        \
199         r0 = 0x100000001 ll;                            \
200         w0 |= w1;                                       \
201         r0 >>= 32;                                      \
202         exit;                                           \
203 "       :
204         : __imm(bpf_get_prandom_u32)
205         : __clobber_all);
206 }
207
208 SEC("socket")
209 __description("or32 imm zero extend check")
210 __success __success_unpriv __retval(0)
211 __naked void or32_imm_zero_extend_check(void)
212 {
213         asm volatile ("                                 \
214         call %[bpf_get_prandom_u32];                    \
215         r1 = 0x1000000000 ll;                           \
216         r0 |= r1;                                       \
217         w0 |= 0;                                        \
218         r0 >>= 32;                                      \
219         r6 = r0;                                        \
220         call %[bpf_get_prandom_u32];                    \
221         r1 = 0x1000000000 ll;                           \
222         r0 |= r1;                                       \
223         w0 |= 1;                                        \
224         r0 >>= 32;                                      \
225         r0 |= r6;                                       \
226         exit;                                           \
227 "       :
228         : __imm(bpf_get_prandom_u32)
229         : __clobber_all);
230 }
231
232 SEC("socket")
233 __description("and32 reg zero extend check")
234 __success __success_unpriv __retval(0)
235 __naked void and32_reg_zero_extend_check(void)
236 {
237         asm volatile ("                                 \
238         call %[bpf_get_prandom_u32];                    \
239         r1 = 0x100000000 ll;                            \
240         r1 |= r0;                                       \
241         r0 = 0x1ffffffff ll;                            \
242         w0 &= w1;                                       \
243         r0 >>= 32;                                      \
244         exit;                                           \
245 "       :
246         : __imm(bpf_get_prandom_u32)
247         : __clobber_all);
248 }
249
250 SEC("socket")
251 __description("and32 imm zero extend check")
252 __success __success_unpriv __retval(0)
253 __naked void and32_imm_zero_extend_check(void)
254 {
255         asm volatile ("                                 \
256         call %[bpf_get_prandom_u32];                    \
257         r1 = 0x1000000000 ll;                           \
258         r0 |= r1;                                       \
259         w0 &= -1;                                       \
260         r0 >>= 32;                                      \
261         r6 = r0;                                        \
262         call %[bpf_get_prandom_u32];                    \
263         r1 = 0x1000000000 ll;                           \
264         r0 |= r1;                                       \
265         w0 &= -2;                                       \
266         r0 >>= 32;                                      \
267         r0 |= r6;                                       \
268         exit;                                           \
269 "       :
270         : __imm(bpf_get_prandom_u32)
271         : __clobber_all);
272 }
273
274 SEC("socket")
275 __description("lsh32 reg zero extend check")
276 __success __success_unpriv __retval(0)
277 __naked void lsh32_reg_zero_extend_check(void)
278 {
279         asm volatile ("                                 \
280         call %[bpf_get_prandom_u32];                    \
281         r1 = 0x100000000 ll;                            \
282         r0 |= r1;                                       \
283         r1 = 1;                                         \
284         w0 <<= w1;                                      \
285         r0 >>= 32;                                      \
286         exit;                                           \
287 "       :
288         : __imm(bpf_get_prandom_u32)
289         : __clobber_all);
290 }
291
292 SEC("socket")
293 __description("lsh32 imm zero extend check")
294 __success __success_unpriv __retval(0)
295 __naked void lsh32_imm_zero_extend_check(void)
296 {
297         asm volatile ("                                 \
298         call %[bpf_get_prandom_u32];                    \
299         r1 = 0x1000000000 ll;                           \
300         r0 |= r1;                                       \
301         w0 <<= 0;                                       \
302         r0 >>= 32;                                      \
303         r6 = r0;                                        \
304         call %[bpf_get_prandom_u32];                    \
305         r1 = 0x1000000000 ll;                           \
306         r0 |= r1;                                       \
307         w0 <<= 1;                                       \
308         r0 >>= 32;                                      \
309         r0 |= r6;                                       \
310         exit;                                           \
311 "       :
312         : __imm(bpf_get_prandom_u32)
313         : __clobber_all);
314 }
315
316 SEC("socket")
317 __description("rsh32 reg zero extend check")
318 __success __success_unpriv __retval(0)
319 __naked void rsh32_reg_zero_extend_check(void)
320 {
321         asm volatile ("                                 \
322         call %[bpf_get_prandom_u32];                    \
323         r1 = 0x1000000000 ll;                           \
324         r0 |= r1;                                       \
325         r1 = 1;                                         \
326         w0 >>= w1;                                      \
327         r0 >>= 32;                                      \
328         exit;                                           \
329 "       :
330         : __imm(bpf_get_prandom_u32)
331         : __clobber_all);
332 }
333
334 SEC("socket")
335 __description("rsh32 imm zero extend check")
336 __success __success_unpriv __retval(0)
337 __naked void rsh32_imm_zero_extend_check(void)
338 {
339         asm volatile ("                                 \
340         call %[bpf_get_prandom_u32];                    \
341         r1 = 0x1000000000 ll;                           \
342         r0 |= r1;                                       \
343         w0 >>= 0;                                       \
344         r0 >>= 32;                                      \
345         r6 = r0;                                        \
346         call %[bpf_get_prandom_u32];                    \
347         r1 = 0x1000000000 ll;                           \
348         r0 |= r1;                                       \
349         w0 >>= 1;                                       \
350         r0 >>= 32;                                      \
351         r0 |= r6;                                       \
352         exit;                                           \
353 "       :
354         : __imm(bpf_get_prandom_u32)
355         : __clobber_all);
356 }
357
358 SEC("socket")
359 __description("neg32 reg zero extend check")
360 __success __success_unpriv __retval(0)
361 __naked void neg32_reg_zero_extend_check(void)
362 {
363         asm volatile ("                                 \
364         call %[bpf_get_prandom_u32];                    \
365         r1 = 0x1000000000 ll;                           \
366         r0 |= r1;                                       \
367         w0 = -w0;                                       \
368         r0 >>= 32;                                      \
369         exit;                                           \
370 "       :
371         : __imm(bpf_get_prandom_u32)
372         : __clobber_all);
373 }
374
375 SEC("socket")
376 __description("mod32 reg zero extend check")
377 __success __success_unpriv __retval(0)
378 __naked void mod32_reg_zero_extend_check(void)
379 {
380         asm volatile ("                                 \
381         call %[bpf_get_prandom_u32];                    \
382         r1 = r0;                                        \
383         r0 = -1;                                        \
384         w0 %%= w1;                                      \
385         r0 >>= 32;                                      \
386         exit;                                           \
387 "       :
388         : __imm(bpf_get_prandom_u32)
389         : __clobber_all);
390 }
391
392 SEC("socket")
393 __description("mod32 imm zero extend check")
394 __success __success_unpriv __retval(0)
395 __naked void mod32_imm_zero_extend_check(void)
396 {
397         asm volatile ("                                 \
398         call %[bpf_get_prandom_u32];                    \
399         r1 = 0x1000000000 ll;                           \
400         r0 |= r1;                                       \
401         w0 %%= 1;                                       \
402         r0 >>= 32;                                      \
403         r6 = r0;                                        \
404         call %[bpf_get_prandom_u32];                    \
405         r1 = 0x1000000000 ll;                           \
406         r0 |= r1;                                       \
407         w0 %%= 2;                                       \
408         r0 >>= 32;                                      \
409         r0 |= r6;                                       \
410         exit;                                           \
411 "       :
412         : __imm(bpf_get_prandom_u32)
413         : __clobber_all);
414 }
415
416 SEC("socket")
417 __description("xor32 reg zero extend check")
418 __success __success_unpriv __retval(0)
419 __naked void xor32_reg_zero_extend_check(void)
420 {
421         asm volatile ("                                 \
422         call %[bpf_get_prandom_u32];                    \
423         r1 = r0;                                        \
424         r0 = 0x100000000 ll;                            \
425         w0 ^= w1;                                       \
426         r0 >>= 32;                                      \
427         exit;                                           \
428 "       :
429         : __imm(bpf_get_prandom_u32)
430         : __clobber_all);
431 }
432
433 SEC("socket")
434 __description("xor32 imm zero extend check")
435 __success __success_unpriv __retval(0)
436 __naked void xor32_imm_zero_extend_check(void)
437 {
438         asm volatile ("                                 \
439         call %[bpf_get_prandom_u32];                    \
440         r1 = 0x1000000000 ll;                           \
441         r0 |= r1;                                       \
442         w0 ^= 1;                                        \
443         r0 >>= 32;                                      \
444         exit;                                           \
445 "       :
446         : __imm(bpf_get_prandom_u32)
447         : __clobber_all);
448 }
449
450 SEC("socket")
451 __description("mov32 reg zero extend check")
452 __success __success_unpriv __retval(0)
453 __naked void mov32_reg_zero_extend_check(void)
454 {
455         asm volatile ("                                 \
456         call %[bpf_get_prandom_u32];                    \
457         r1 = 0x100000000 ll;                            \
458         r1 |= r0;                                       \
459         r0 = 0x100000000 ll;                            \
460         w0 = w1;                                        \
461         r0 >>= 32;                                      \
462         exit;                                           \
463 "       :
464         : __imm(bpf_get_prandom_u32)
465         : __clobber_all);
466 }
467
468 SEC("socket")
469 __description("mov32 imm zero extend check")
470 __success __success_unpriv __retval(0)
471 __naked void mov32_imm_zero_extend_check(void)
472 {
473         asm volatile ("                                 \
474         call %[bpf_get_prandom_u32];                    \
475         r1 = 0x1000000000 ll;                           \
476         r0 |= r1;                                       \
477         w0 = 0;                                         \
478         r0 >>= 32;                                      \
479         r6 = r0;                                        \
480         call %[bpf_get_prandom_u32];                    \
481         r1 = 0x1000000000 ll;                           \
482         r0 |= r1;                                       \
483         w0 = 1;                                         \
484         r0 >>= 32;                                      \
485         r0 |= r6;                                       \
486         exit;                                           \
487 "       :
488         : __imm(bpf_get_prandom_u32)
489         : __clobber_all);
490 }
491
492 SEC("socket")
493 __description("arsh32 reg zero extend check")
494 __success __success_unpriv __retval(0)
495 __naked void arsh32_reg_zero_extend_check(void)
496 {
497         asm volatile ("                                 \
498         call %[bpf_get_prandom_u32];                    \
499         r1 = 0x1000000000 ll;                           \
500         r0 |= r1;                                       \
501         r1 = 1;                                         \
502         w0 s>>= w1;                                     \
503         r0 >>= 32;                                      \
504         exit;                                           \
505 "       :
506         : __imm(bpf_get_prandom_u32)
507         : __clobber_all);
508 }
509
510 SEC("socket")
511 __description("arsh32 imm zero extend check")
512 __success __success_unpriv __retval(0)
513 __naked void arsh32_imm_zero_extend_check(void)
514 {
515         asm volatile ("                                 \
516         call %[bpf_get_prandom_u32];                    \
517         r1 = 0x1000000000 ll;                           \
518         r0 |= r1;                                       \
519         w0 s>>= 0;                                      \
520         r0 >>= 32;                                      \
521         r6 = r0;                                        \
522         call %[bpf_get_prandom_u32];                    \
523         r1 = 0x1000000000 ll;                           \
524         r0 |= r1;                                       \
525         w0 s>>= 1;                                      \
526         r0 >>= 32;                                      \
527         r0 |= r6;                                       \
528         exit;                                           \
529 "       :
530         : __imm(bpf_get_prandom_u32)
531         : __clobber_all);
532 }
533
534 SEC("socket")
535 __description("end16 (to_le) reg zero extend check")
536 __success __success_unpriv __retval(0)
537 __naked void le_reg_zero_extend_check_1(void)
538 {
539         asm volatile ("                                 \
540         call %[bpf_get_prandom_u32];                    \
541         r6 = r0;                                        \
542         r6 <<= 32;                                      \
543         call %[bpf_get_prandom_u32];                    \
544         r0 |= r6;                                       \
545         r0 = le16 r0;                                   \
546         r0 >>= 32;                                      \
547         exit;                                           \
548 "       :
549         : __imm(bpf_get_prandom_u32)
550         : __clobber_all);
551 }
552
553 SEC("socket")
554 __description("end32 (to_le) reg zero extend check")
555 __success __success_unpriv __retval(0)
556 __naked void le_reg_zero_extend_check_2(void)
557 {
558         asm volatile ("                                 \
559         call %[bpf_get_prandom_u32];                    \
560         r6 = r0;                                        \
561         r6 <<= 32;                                      \
562         call %[bpf_get_prandom_u32];                    \
563         r0 |= r6;                                       \
564         r0 = le32 r0;                                   \
565         r0 >>= 32;                                      \
566         exit;                                           \
567 "       :
568         : __imm(bpf_get_prandom_u32)
569         : __clobber_all);
570 }
571
572 SEC("socket")
573 __description("end16 (to_be) reg zero extend check")
574 __success __success_unpriv __retval(0)
575 __naked void be_reg_zero_extend_check_1(void)
576 {
577         asm volatile ("                                 \
578         call %[bpf_get_prandom_u32];                    \
579         r6 = r0;                                        \
580         r6 <<= 32;                                      \
581         call %[bpf_get_prandom_u32];                    \
582         r0 |= r6;                                       \
583         r0 = be16 r0;                                   \
584         r0 >>= 32;                                      \
585         exit;                                           \
586 "       :
587         : __imm(bpf_get_prandom_u32)
588         : __clobber_all);
589 }
590
591 SEC("socket")
592 __description("end32 (to_be) reg zero extend check")
593 __success __success_unpriv __retval(0)
594 __naked void be_reg_zero_extend_check_2(void)
595 {
596         asm volatile ("                                 \
597         call %[bpf_get_prandom_u32];                    \
598         r6 = r0;                                        \
599         r6 <<= 32;                                      \
600         call %[bpf_get_prandom_u32];                    \
601         r0 |= r6;                                       \
602         r0 = be32 r0;                                   \
603         r0 >>= 32;                                      \
604         exit;                                           \
605 "       :
606         : __imm(bpf_get_prandom_u32)
607         : __clobber_all);
608 }
609
610 SEC("socket")
611 __description("ldx_b zero extend check")
612 __success __success_unpriv __retval(0)
613 __naked void ldx_b_zero_extend_check(void)
614 {
615         asm volatile ("                                 \
616         r6 = r10;                                       \
617         r6 += -4;                                       \
618         r7 = 0xfaceb00c;                                \
619         *(u32*)(r6 + 0) = r7;                           \
620         call %[bpf_get_prandom_u32];                    \
621         r1 = 0x1000000000 ll;                           \
622         r0 |= r1;                                       \
623         r0 = *(u8*)(r6 + 0);                            \
624         r0 >>= 32;                                      \
625         exit;                                           \
626 "       :
627         : __imm(bpf_get_prandom_u32)
628         : __clobber_all);
629 }
630
631 SEC("socket")
632 __description("ldx_h zero extend check")
633 __success __success_unpriv __retval(0)
634 __naked void ldx_h_zero_extend_check(void)
635 {
636         asm volatile ("                                 \
637         r6 = r10;                                       \
638         r6 += -4;                                       \
639         r7 = 0xfaceb00c;                                \
640         *(u32*)(r6 + 0) = r7;                           \
641         call %[bpf_get_prandom_u32];                    \
642         r1 = 0x1000000000 ll;                           \
643         r0 |= r1;                                       \
644         r0 = *(u16*)(r6 + 0);                           \
645         r0 >>= 32;                                      \
646         exit;                                           \
647 "       :
648         : __imm(bpf_get_prandom_u32)
649         : __clobber_all);
650 }
651
652 SEC("socket")
653 __description("ldx_w zero extend check")
654 __success __success_unpriv __retval(0)
655 __naked void ldx_w_zero_extend_check(void)
656 {
657         asm volatile ("                                 \
658         r6 = r10;                                       \
659         r6 += -4;                                       \
660         r7 = 0xfaceb00c;                                \
661         *(u32*)(r6 + 0) = r7;                           \
662         call %[bpf_get_prandom_u32];                    \
663         r1 = 0x1000000000 ll;                           \
664         r0 |= r1;                                       \
665         r0 = *(u32*)(r6 + 0);                           \
666         r0 >>= 32;                                      \
667         exit;                                           \
668 "       :
669         : __imm(bpf_get_prandom_u32)
670         : __clobber_all);
671 }
672
673 char _license[] SEC("license") = "GPL";