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