674 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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 defining9 * sub-registers, meaning:10 * - All insns under BPF_ALU class. Their BPF_ALU32 variants or narrow width11 * 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 to16 * prevent potential optimizations done by verifier or JIT back-ends which could17 * optimize register back into constant when range info shows one register is a18 * 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