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
21SEC("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
38SEC("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
68SEC("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
85SEC("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
109SEC("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
126SEC("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
150SEC("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
167SEC("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
191SEC("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
208SEC("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
232SEC("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
250SEC("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
274SEC("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
292SEC("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
316SEC("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
334SEC("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
358SEC("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
375SEC("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
392SEC("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
416SEC("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
433SEC("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
450SEC("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
468SEC("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
492SEC("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
510SEC("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
534SEC("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
553SEC("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
572SEC("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
591SEC("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
610SEC("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
631SEC("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
652SEC("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
673char _license[] SEC("license") = "GPL";
674

source code of linux/tools/testing/selftests/bpf/progs/verifier_subreg.c