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"; 674