1 // SPDX-License-Identifier: GPL-2.0 2 /* Converted from tools/testing/selftests/bpf/verifier/value_ptr_arith.c */ 3 4 #include <linux/bpf.h> 5 #include <bpf/bpf_helpers.h> 6 #include <errno.h> 7 #include "bpf_misc.h" 8 9 #define MAX_ENTRIES 11 10 11 struct test_val { 12 unsigned int index; 13 int foo[MAX_ENTRIES]; 14 }; 15 16 struct { 17 __uint(type, BPF_MAP_TYPE_ARRAY); 18 __uint(max_entries, 1); 19 __type(key, int); 20 __type(value, struct test_val); 21 } map_array_48b SEC(".maps"); 22 23 struct other_val { 24 long long foo; 25 long long bar; 26 }; 27 28 struct { 29 __uint(type, BPF_MAP_TYPE_HASH); 30 __uint(max_entries, 1); 31 __type(key, long long); 32 __type(value, struct other_val); 33 } map_hash_16b SEC(".maps"); 34 35 struct { 36 __uint(type, BPF_MAP_TYPE_HASH); 37 __uint(max_entries, 1); 38 __type(key, long long); 39 __type(value, struct test_val); 40 } map_hash_48b SEC(".maps"); 41 42 SEC("socket") 43 __description("map access: known scalar += value_ptr unknown vs const") 44 __success __failure_unpriv 45 __msg_unpriv("R1 tried to add from different maps, paths or scalars") 46 __retval(1) 47 __naked void value_ptr_unknown_vs_const(void) 48 { 49 asm volatile (" \ 50 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 51 r1 = 0; \ 52 *(u64*)(r10 - 8) = r1; \ 53 r2 = r10; \ 54 r2 += -8; \ 55 if r0 == 1 goto l0_%=; \ 56 r1 = %[map_hash_16b] ll; \ 57 if r0 != 1 goto l1_%=; \ 58 l0_%=: r1 = %[map_array_48b] ll; \ 59 l1_%=: call %[bpf_map_lookup_elem]; \ 60 if r0 == 0 goto l2_%=; \ 61 r4 = *(u8*)(r0 + 0); \ 62 if r4 == 1 goto l3_%=; \ 63 r1 = 6; \ 64 r1 = -r1; \ 65 r1 &= 0x7; \ 66 goto l4_%=; \ 67 l3_%=: r1 = 3; \ 68 l4_%=: r1 += r0; \ 69 r0 = *(u8*)(r1 + 0); \ 70 l2_%=: r0 = 1; \ 71 exit; \ 72 " : 73 : __imm(bpf_map_lookup_elem), 74 __imm_addr(map_array_48b), 75 __imm_addr(map_hash_16b), 76 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 77 : __clobber_all); 78 } 79 80 SEC("socket") 81 __description("map access: known scalar += value_ptr const vs unknown") 82 __success __failure_unpriv 83 __msg_unpriv("R1 tried to add from different maps, paths or scalars") 84 __retval(1) 85 __naked void value_ptr_const_vs_unknown(void) 86 { 87 asm volatile (" \ 88 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 89 r1 = 0; \ 90 *(u64*)(r10 - 8) = r1; \ 91 r2 = r10; \ 92 r2 += -8; \ 93 if r0 == 1 goto l0_%=; \ 94 r1 = %[map_hash_16b] ll; \ 95 if r0 != 1 goto l1_%=; \ 96 l0_%=: r1 = %[map_array_48b] ll; \ 97 l1_%=: call %[bpf_map_lookup_elem]; \ 98 if r0 == 0 goto l2_%=; \ 99 r4 = *(u8*)(r0 + 0); \ 100 if r4 == 1 goto l3_%=; \ 101 r1 = 3; \ 102 goto l4_%=; \ 103 l3_%=: r1 = 6; \ 104 r1 = -r1; \ 105 r1 &= 0x7; \ 106 l4_%=: r1 += r0; \ 107 r0 = *(u8*)(r1 + 0); \ 108 l2_%=: r0 = 1; \ 109 exit; \ 110 " : 111 : __imm(bpf_map_lookup_elem), 112 __imm_addr(map_array_48b), 113 __imm_addr(map_hash_16b), 114 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 115 : __clobber_all); 116 } 117 118 SEC("socket") 119 __description("map access: known scalar += value_ptr const vs const (ne)") 120 __success __failure_unpriv 121 __msg_unpriv("R1 tried to add from different maps, paths or scalars") 122 __retval(1) 123 __naked void ptr_const_vs_const_ne(void) 124 { 125 asm volatile (" \ 126 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 127 r1 = 0; \ 128 *(u64*)(r10 - 8) = r1; \ 129 r2 = r10; \ 130 r2 += -8; \ 131 if r0 == 1 goto l0_%=; \ 132 r1 = %[map_hash_16b] ll; \ 133 if r0 != 1 goto l1_%=; \ 134 l0_%=: r1 = %[map_array_48b] ll; \ 135 l1_%=: call %[bpf_map_lookup_elem]; \ 136 if r0 == 0 goto l2_%=; \ 137 r4 = *(u8*)(r0 + 0); \ 138 if r4 == 1 goto l3_%=; \ 139 r1 = 3; \ 140 goto l4_%=; \ 141 l3_%=: r1 = 5; \ 142 l4_%=: r1 += r0; \ 143 r0 = *(u8*)(r1 + 0); \ 144 l2_%=: r0 = 1; \ 145 exit; \ 146 " : 147 : __imm(bpf_map_lookup_elem), 148 __imm_addr(map_array_48b), 149 __imm_addr(map_hash_16b), 150 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 151 : __clobber_all); 152 } 153 154 SEC("socket") 155 __description("map access: known scalar += value_ptr const vs const (eq)") 156 __success __success_unpriv __retval(1) 157 __naked void ptr_const_vs_const_eq(void) 158 { 159 asm volatile (" \ 160 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 161 r1 = 0; \ 162 *(u64*)(r10 - 8) = r1; \ 163 r2 = r10; \ 164 r2 += -8; \ 165 if r0 == 1 goto l0_%=; \ 166 r1 = %[map_hash_16b] ll; \ 167 if r0 != 1 goto l1_%=; \ 168 l0_%=: r1 = %[map_array_48b] ll; \ 169 l1_%=: call %[bpf_map_lookup_elem]; \ 170 if r0 == 0 goto l2_%=; \ 171 r4 = *(u8*)(r0 + 0); \ 172 if r4 == 1 goto l3_%=; \ 173 r1 = 5; \ 174 goto l4_%=; \ 175 l3_%=: r1 = 5; \ 176 l4_%=: r1 += r0; \ 177 r0 = *(u8*)(r1 + 0); \ 178 l2_%=: r0 = 1; \ 179 exit; \ 180 " : 181 : __imm(bpf_map_lookup_elem), 182 __imm_addr(map_array_48b), 183 __imm_addr(map_hash_16b), 184 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 185 : __clobber_all); 186 } 187 188 SEC("socket") 189 __description("map access: known scalar += value_ptr unknown vs unknown (eq)") 190 __success __success_unpriv __retval(1) 191 __naked void ptr_unknown_vs_unknown_eq(void) 192 { 193 asm volatile (" \ 194 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 195 r1 = 0; \ 196 *(u64*)(r10 - 8) = r1; \ 197 r2 = r10; \ 198 r2 += -8; \ 199 if r0 == 1 goto l0_%=; \ 200 r1 = %[map_hash_16b] ll; \ 201 if r0 != 1 goto l1_%=; \ 202 l0_%=: r1 = %[map_array_48b] ll; \ 203 l1_%=: call %[bpf_map_lookup_elem]; \ 204 if r0 == 0 goto l2_%=; \ 205 r4 = *(u8*)(r0 + 0); \ 206 if r4 == 1 goto l3_%=; \ 207 r1 = 6; \ 208 r1 = -r1; \ 209 r1 &= 0x7; \ 210 goto l4_%=; \ 211 l3_%=: r1 = 6; \ 212 r1 = -r1; \ 213 r1 &= 0x7; \ 214 l4_%=: r1 += r0; \ 215 r0 = *(u8*)(r1 + 0); \ 216 l2_%=: r0 = 1; \ 217 exit; \ 218 " : 219 : __imm(bpf_map_lookup_elem), 220 __imm_addr(map_array_48b), 221 __imm_addr(map_hash_16b), 222 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 223 : __clobber_all); 224 } 225 226 SEC("socket") 227 __description("map access: known scalar += value_ptr unknown vs unknown (lt)") 228 __success __failure_unpriv 229 __msg_unpriv("R1 tried to add from different maps, paths or scalars") 230 __retval(1) 231 __naked void ptr_unknown_vs_unknown_lt(void) 232 { 233 asm volatile (" \ 234 r8 = r1; \ 235 call %[bpf_get_prandom_u32]; \ 236 r9 = r0; \ 237 r1 = r8; \ 238 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 239 r1 = 0; \ 240 *(u64*)(r10 - 8) = r1; \ 241 r2 = r10; \ 242 r2 += -8; \ 243 if r0 == 1 goto l0_%=; \ 244 r1 = %[map_hash_16b] ll; \ 245 if r0 != 1 goto l1_%=; \ 246 l0_%=: r1 = %[map_array_48b] ll; \ 247 l1_%=: call %[bpf_map_lookup_elem]; \ 248 if r0 == 0 goto l2_%=; \ 249 r4 = *(u8*)(r0 + 0); \ 250 if r4 == 1 goto l3_%=; \ 251 r1 = 6; \ 252 r1 = r9; \ 253 r1 &= 0x3; \ 254 goto l4_%=; \ 255 l3_%=: r1 = 6; \ 256 r1 = r9; \ 257 r1 &= 0x7; \ 258 l4_%=: r1 += r0; \ 259 r0 = *(u8*)(r1 + 0); \ 260 l2_%=: r0 = 1; \ 261 exit; \ 262 " : 263 : __imm(bpf_map_lookup_elem), 264 __imm_addr(map_array_48b), 265 __imm_addr(map_hash_16b), 266 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)), 267 __imm(bpf_get_prandom_u32) 268 : __clobber_all); 269 } 270 271 SEC("socket") 272 __description("map access: known scalar += value_ptr unknown vs unknown (gt)") 273 __success __failure_unpriv 274 __msg_unpriv("R1 tried to add from different maps, paths or scalars") 275 __retval(1) 276 __naked void ptr_unknown_vs_unknown_gt(void) 277 { 278 asm volatile (" \ 279 r8 = r1; \ 280 call %[bpf_get_prandom_u32]; \ 281 r9 = r0; \ 282 r1 = r8; \ 283 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 284 r1 = 0; \ 285 *(u64*)(r10 - 8) = r1; \ 286 r2 = r10; \ 287 r2 += -8; \ 288 if r0 == 1 goto l0_%=; \ 289 r1 = %[map_hash_16b] ll; \ 290 if r0 != 1 goto l1_%=; \ 291 l0_%=: r1 = %[map_array_48b] ll; \ 292 l1_%=: call %[bpf_map_lookup_elem]; \ 293 if r0 == 0 goto l2_%=; \ 294 r4 = *(u8*)(r0 + 0); \ 295 if r4 == 1 goto l3_%=; \ 296 r1 = 6; \ 297 r1 = r9; \ 298 r1 &= 0x7; \ 299 goto l4_%=; \ 300 l3_%=: r1 = 6; \ 301 r1 = r9; \ 302 r1 &= 0x3; \ 303 l4_%=: r1 += r0; \ 304 r0 = *(u8*)(r1 + 0); \ 305 l2_%=: r0 = 1; \ 306 exit; \ 307 " : 308 : __imm(bpf_map_lookup_elem), 309 __imm_addr(map_array_48b), 310 __imm_addr(map_hash_16b), 311 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)), 312 __imm(bpf_get_prandom_u32) 313 : __clobber_all); 314 } 315 316 SEC("socket") 317 __description("map access: known scalar += value_ptr from different maps") 318 __success __success_unpriv __retval(1) 319 __naked void value_ptr_from_different_maps(void) 320 { 321 asm volatile (" \ 322 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 323 r1 = 0; \ 324 *(u64*)(r10 - 8) = r1; \ 325 r2 = r10; \ 326 r2 += -8; \ 327 if r0 == 1 goto l0_%=; \ 328 r1 = %[map_hash_16b] ll; \ 329 if r0 != 1 goto l1_%=; \ 330 l0_%=: r1 = %[map_array_48b] ll; \ 331 l1_%=: call %[bpf_map_lookup_elem]; \ 332 if r0 == 0 goto l2_%=; \ 333 r1 = 4; \ 334 r1 += r0; \ 335 r0 = *(u8*)(r1 + 0); \ 336 l2_%=: r0 = 1; \ 337 exit; \ 338 " : 339 : __imm(bpf_map_lookup_elem), 340 __imm_addr(map_array_48b), 341 __imm_addr(map_hash_16b), 342 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 343 : __clobber_all); 344 } 345 346 SEC("socket") 347 __description("map access: value_ptr -= known scalar from different maps") 348 __success __failure_unpriv 349 __msg_unpriv("R0 min value is outside of the allowed memory range") 350 __retval(1) 351 __naked void known_scalar_from_different_maps(void) 352 { 353 asm volatile (" \ 354 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 355 r1 = 0; \ 356 *(u64*)(r10 - 8) = r1; \ 357 r2 = r10; \ 358 r2 += -8; \ 359 if r0 == 1 goto l0_%=; \ 360 r1 = %[map_hash_16b] ll; \ 361 if r0 != 1 goto l1_%=; \ 362 l0_%=: r1 = %[map_array_48b] ll; \ 363 l1_%=: call %[bpf_map_lookup_elem]; \ 364 if r0 == 0 goto l2_%=; \ 365 r1 = 4; \ 366 r0 -= r1; \ 367 r0 += r1; \ 368 r0 = *(u8*)(r0 + 0); \ 369 l2_%=: r0 = 1; \ 370 exit; \ 371 " : 372 : __imm(bpf_map_lookup_elem), 373 __imm_addr(map_array_48b), 374 __imm_addr(map_hash_16b), 375 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 376 : __clobber_all); 377 } 378 379 SEC("socket") 380 __description("map access: known scalar += value_ptr from different maps, but same value properties") 381 __success __success_unpriv __retval(1) 382 __naked void maps_but_same_value_properties(void) 383 { 384 asm volatile (" \ 385 r0 = *(u32*)(r1 + %[__sk_buff_len]); \ 386 r1 = 0; \ 387 *(u64*)(r10 - 8) = r1; \ 388 r2 = r10; \ 389 r2 += -8; \ 390 if r0 == 1 goto l0_%=; \ 391 r1 = %[map_hash_48b] ll; \ 392 if r0 != 1 goto l1_%=; \ 393 l0_%=: r1 = %[map_array_48b] ll; \ 394 l1_%=: call %[bpf_map_lookup_elem]; \ 395 if r0 == 0 goto l2_%=; \ 396 r1 = 4; \ 397 r1 += r0; \ 398 r0 = *(u8*)(r1 + 0); \ 399 l2_%=: r0 = 1; \ 400 exit; \ 401 " : 402 : __imm(bpf_map_lookup_elem), 403 __imm_addr(map_array_48b), 404 __imm_addr(map_hash_48b), 405 __imm_const(__sk_buff_len, offsetof(struct __sk_buff, len)) 406 : __clobber_all); 407 } 408 409 SEC("socket") 410 __description("map access: mixing value pointer and scalar, 1") 411 __success __failure_unpriv 412 __msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root") 413 __retval(0) 414 __naked void value_pointer_and_scalar_1(void) 415 { 416 asm volatile (" \ 417 /* load map value pointer into r0 and r2 */ \ 418 r0 = 1; \ 419 r1 = %[map_array_48b] ll; \ 420 r2 = r10; \ 421 r2 += -16; \ 422 r6 = 0; \ 423 *(u64*)(r10 - 16) = r6; \ 424 call %[bpf_map_lookup_elem]; \ 425 if r0 != 0 goto l0_%=; \ 426 exit; \ 427 l0_%=: /* load some number from the map into r1 */ \ 428 r1 = *(u8*)(r0 + 0); \ 429 /* depending on r1, branch: */ \ 430 if r1 != 0 goto l1_%=; \ 431 /* branch A */ \ 432 r2 = r0; \ 433 r3 = 0; \ 434 goto l2_%=; \ 435 l1_%=: /* branch B */ \ 436 r2 = 0; \ 437 r3 = 0x100000; \ 438 l2_%=: /* common instruction */ \ 439 r2 += r3; \ 440 /* depending on r1, branch: */ \ 441 if r1 != 0 goto l3_%=; \ 442 /* branch A */ \ 443 goto l4_%=; \ 444 l3_%=: /* branch B */ \ 445 r0 = 0x13371337; \ 446 /* verifier follows fall-through */ \ 447 /* unpriv: nospec (inserted to prevent `R2 pointer comparison prohibited`) */\ 448 if r2 != 0x100000 goto l4_%=; \ 449 r0 = 0; \ 450 exit; \ 451 l4_%=: /* fake-dead code; targeted from branch A to \ 452 * prevent dead code sanitization \ 453 */ \ 454 r0 = *(u8*)(r0 + 0); \ 455 r0 = 0; \ 456 exit; \ 457 " : 458 : __imm(bpf_map_lookup_elem), 459 __imm_addr(map_array_48b) 460 : __clobber_all); 461 } 462 463 SEC("socket") 464 __description("map access: mixing value pointer and scalar, 2") 465 __success __failure_unpriv 466 __msg_unpriv("R2 tried to add from different maps, paths or scalars, pointer arithmetic with it prohibited for !root") 467 __retval(0) 468 __naked void value_pointer_and_scalar_2(void) 469 { 470 asm volatile (" \ 471 /* load map value pointer into r0 and r2 */ \ 472 r0 = 1; \ 473 r1 = %[map_array_48b] ll; \ 474 r2 = r10; \ 475 r2 += -16; \ 476 r6 = 0; \ 477 *(u64*)(r10 - 16) = r6; \ 478 call %[bpf_map_lookup_elem]; \ 479 if r0 != 0 goto l0_%=; \ 480 exit; \ 481 l0_%=: /* load some number from the map into r1 */ \ 482 r1 = *(u8*)(r0 + 0); \ 483 /* depending on r1, branch: */ \ 484 if r1 == 0 goto l1_%=; \ 485 /* branch A */ \ 486 r2 = 0; \ 487 r3 = 0x100000; \ 488 goto l2_%=; \ 489 l1_%=: /* branch B */ \ 490 r2 = r0; \ 491 r3 = 0; \ 492 l2_%=: /* common instruction */ \ 493 r2 += r3; \ 494 /* depending on r1, branch: */ \ 495 if r1 != 0 goto l3_%=; \ 496 /* branch A */ \ 497 goto l4_%=; \ 498 l3_%=: /* branch B */ \ 499 r0 = 0x13371337; \ 500 /* verifier follows fall-through */ \ 501 if r2 != 0x100000 goto l4_%=; \ 502 r0 = 0; \ 503 exit; \ 504 l4_%=: /* fake-dead code; targeted from branch A to \ 505 * prevent dead code sanitization, rejected \ 506 * via branch B however \ 507 */ \ 508 /* unpriv: nospec (inserted to prevent `R0 invalid mem access 'scalar'`) */\ 509 r0 = *(u8*)(r0 + 0); \ 510 r0 = 0; \ 511 exit; \ 512 " : 513 : __imm(bpf_map_lookup_elem), 514 __imm_addr(map_array_48b) 515 : __clobber_all); 516 } 517 518 SEC("socket") 519 __description("sanitation: alu with different scalars 1") 520 __success __success_unpriv __retval(0x100000) 521 __naked void alu_with_different_scalars_1(void) 522 { 523 asm volatile (" \ 524 r0 = 1; \ 525 r1 = %[map_array_48b] ll; \ 526 r2 = r10; \ 527 r2 += -16; \ 528 r6 = 0; \ 529 *(u64*)(r10 - 16) = r6; \ 530 call %[bpf_map_lookup_elem]; \ 531 if r0 != 0 goto l0_%=; \ 532 exit; \ 533 l0_%=: r1 = *(u32*)(r0 + 0); \ 534 if r1 == 0 goto l1_%=; \ 535 r2 = 0; \ 536 r3 = 0x100000; \ 537 goto l2_%=; \ 538 l1_%=: r2 = 42; \ 539 r3 = 0x100001; \ 540 l2_%=: r2 += r3; \ 541 r0 = r2; \ 542 exit; \ 543 " : 544 : __imm(bpf_map_lookup_elem), 545 __imm_addr(map_array_48b) 546 : __clobber_all); 547 } 548 549 SEC("socket") 550 __description("sanitation: alu with different scalars 2") 551 __success __success_unpriv __retval(0) 552 __naked void alu_with_different_scalars_2(void) 553 { 554 asm volatile (" \ 555 r0 = 1; \ 556 r1 = %[map_array_48b] ll; \ 557 r6 = r1; \ 558 r2 = r10; \ 559 r2 += -16; \ 560 r7 = 0; \ 561 *(u64*)(r10 - 16) = r7; \ 562 call %[bpf_map_delete_elem]; \ 563 r7 = r0; \ 564 r1 = r6; \ 565 r2 = r10; \ 566 r2 += -16; \ 567 call %[bpf_map_delete_elem]; \ 568 r6 = r0; \ 569 r8 = r6; \ 570 r8 += r7; \ 571 r0 = r8; \ 572 r0 += %[einval]; \ 573 r0 += %[einval]; \ 574 exit; \ 575 " : 576 : __imm(bpf_map_delete_elem), 577 __imm_addr(map_array_48b), 578 __imm_const(einval, EINVAL) 579 : __clobber_all); 580 } 581 582 SEC("socket") 583 __description("sanitation: alu with different scalars 3") 584 __success __success_unpriv __retval(0) 585 __naked void alu_with_different_scalars_3(void) 586 { 587 asm volatile (" \ 588 r0 = %[einval]; \ 589 r0 *= -1; \ 590 r7 = r0; \ 591 r0 = %[einval]; \ 592 r0 *= -1; \ 593 r6 = r0; \ 594 r8 = r6; \ 595 r8 += r7; \ 596 r0 = r8; \ 597 r0 += %[einval]; \ 598 r0 += %[einval]; \ 599 exit; \ 600 " : 601 : __imm_const(einval, EINVAL) 602 : __clobber_all); 603 } 604 605 SEC("socket") 606 __description("map access: value_ptr += known scalar, upper oob arith, test 1") 607 __success __failure_unpriv 608 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 609 __retval(1) 610 __naked void upper_oob_arith_test_1(void) 611 { 612 asm volatile (" \ 613 r1 = 0; \ 614 *(u64*)(r10 - 8) = r1; \ 615 r2 = r10; \ 616 r2 += -8; \ 617 r1 = %[map_array_48b] ll; \ 618 call %[bpf_map_lookup_elem]; \ 619 if r0 == 0 goto l0_%=; \ 620 r1 = 48; \ 621 r0 += r1; \ 622 r0 -= r1; \ 623 r0 = *(u8*)(r0 + 0); \ 624 l0_%=: r0 = 1; \ 625 exit; \ 626 " : 627 : __imm(bpf_map_lookup_elem), 628 __imm_addr(map_array_48b) 629 : __clobber_all); 630 } 631 632 SEC("socket") 633 __description("map access: value_ptr += known scalar, upper oob arith, test 2") 634 __success __failure_unpriv 635 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 636 __retval(1) 637 __naked void upper_oob_arith_test_2(void) 638 { 639 asm volatile (" \ 640 r1 = 0; \ 641 *(u64*)(r10 - 8) = r1; \ 642 r2 = r10; \ 643 r2 += -8; \ 644 r1 = %[map_array_48b] ll; \ 645 call %[bpf_map_lookup_elem]; \ 646 if r0 == 0 goto l0_%=; \ 647 r1 = 49; \ 648 r0 += r1; \ 649 r0 -= r1; \ 650 r0 = *(u8*)(r0 + 0); \ 651 l0_%=: r0 = 1; \ 652 exit; \ 653 " : 654 : __imm(bpf_map_lookup_elem), 655 __imm_addr(map_array_48b) 656 : __clobber_all); 657 } 658 659 SEC("socket") 660 __description("map access: value_ptr += known scalar, upper oob arith, test 3") 661 __success __success_unpriv __retval(1) 662 __naked void upper_oob_arith_test_3(void) 663 { 664 asm volatile (" \ 665 r1 = 0; \ 666 *(u64*)(r10 - 8) = r1; \ 667 r2 = r10; \ 668 r2 += -8; \ 669 r1 = %[map_array_48b] ll; \ 670 call %[bpf_map_lookup_elem]; \ 671 if r0 == 0 goto l0_%=; \ 672 r1 = 47; \ 673 r0 += r1; \ 674 r0 -= r1; \ 675 r0 = *(u8*)(r0 + 0); \ 676 l0_%=: r0 = 1; \ 677 exit; \ 678 " : 679 : __imm(bpf_map_lookup_elem), 680 __imm_addr(map_array_48b) 681 : __clobber_all); 682 } 683 684 SEC("socket") 685 __description("map access: value_ptr -= known scalar, lower oob arith, test 1") 686 __failure __msg("R0 min value is outside of the allowed memory range") 687 __failure_unpriv 688 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 689 __naked void lower_oob_arith_test_1(void) 690 { 691 asm volatile (" \ 692 r1 = 0; \ 693 *(u64*)(r10 - 8) = r1; \ 694 r2 = r10; \ 695 r2 += -8; \ 696 r1 = %[map_array_48b] ll; \ 697 call %[bpf_map_lookup_elem]; \ 698 if r0 == 0 goto l0_%=; \ 699 r1 = 47; \ 700 r0 += r1; \ 701 r1 = 48; \ 702 r0 -= r1; \ 703 r0 = *(u8*)(r0 + 0); \ 704 l0_%=: r0 = 1; \ 705 exit; \ 706 " : 707 : __imm(bpf_map_lookup_elem), 708 __imm_addr(map_array_48b) 709 : __clobber_all); 710 } 711 712 SEC("socket") 713 __description("map access: value_ptr -= known scalar, lower oob arith, test 2") 714 __success __failure_unpriv 715 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 716 __retval(1) 717 __naked void lower_oob_arith_test_2(void) 718 { 719 asm volatile (" \ 720 r1 = 0; \ 721 *(u64*)(r10 - 8) = r1; \ 722 r2 = r10; \ 723 r2 += -8; \ 724 r1 = %[map_array_48b] ll; \ 725 call %[bpf_map_lookup_elem]; \ 726 if r0 == 0 goto l0_%=; \ 727 r1 = 47; \ 728 r0 += r1; \ 729 r1 = 48; \ 730 r0 -= r1; \ 731 r1 = 1; \ 732 r0 += r1; \ 733 r0 = *(u8*)(r0 + 0); \ 734 l0_%=: r0 = 1; \ 735 exit; \ 736 " : 737 : __imm(bpf_map_lookup_elem), 738 __imm_addr(map_array_48b) 739 : __clobber_all); 740 } 741 742 SEC("socket") 743 __description("map access: value_ptr -= known scalar, lower oob arith, test 3") 744 __success __success_unpriv __retval(1) 745 __naked void lower_oob_arith_test_3(void) 746 { 747 asm volatile (" \ 748 r1 = 0; \ 749 *(u64*)(r10 - 8) = r1; \ 750 r2 = r10; \ 751 r2 += -8; \ 752 r1 = %[map_array_48b] ll; \ 753 call %[bpf_map_lookup_elem]; \ 754 if r0 == 0 goto l0_%=; \ 755 r1 = 47; \ 756 r0 += r1; \ 757 r1 = 47; \ 758 r0 -= r1; \ 759 r0 = *(u8*)(r0 + 0); \ 760 l0_%=: r0 = 1; \ 761 exit; \ 762 " : 763 : __imm(bpf_map_lookup_elem), 764 __imm_addr(map_array_48b) 765 : __clobber_all); 766 } 767 768 SEC("socket") 769 __description("map access: known scalar += value_ptr") 770 __success __success_unpriv __retval(1) 771 __naked void access_known_scalar_value_ptr_1(void) 772 { 773 asm volatile (" \ 774 r1 = 0; \ 775 *(u64*)(r10 - 8) = r1; \ 776 r2 = r10; \ 777 r2 += -8; \ 778 r1 = %[map_array_48b] ll; \ 779 call %[bpf_map_lookup_elem]; \ 780 if r0 == 0 goto l0_%=; \ 781 r1 = 4; \ 782 r1 += r0; \ 783 r0 = *(u8*)(r1 + 0); \ 784 l0_%=: r0 = 1; \ 785 exit; \ 786 " : 787 : __imm(bpf_map_lookup_elem), 788 __imm_addr(map_array_48b) 789 : __clobber_all); 790 } 791 792 SEC("socket") 793 __description("map access: value_ptr += known scalar, 1") 794 __success __success_unpriv __retval(1) 795 __naked void value_ptr_known_scalar_1(void) 796 { 797 asm volatile (" \ 798 r1 = 0; \ 799 *(u64*)(r10 - 8) = r1; \ 800 r2 = r10; \ 801 r2 += -8; \ 802 r1 = %[map_array_48b] ll; \ 803 call %[bpf_map_lookup_elem]; \ 804 if r0 == 0 goto l0_%=; \ 805 r1 = 4; \ 806 r0 += r1; \ 807 r1 = *(u8*)(r0 + 0); \ 808 l0_%=: r0 = 1; \ 809 exit; \ 810 " : 811 : __imm(bpf_map_lookup_elem), 812 __imm_addr(map_array_48b) 813 : __clobber_all); 814 } 815 816 SEC("socket") 817 __description("map access: value_ptr += known scalar, 2") 818 __failure __msg("invalid access to map value") 819 __failure_unpriv 820 __naked void value_ptr_known_scalar_2_1(void) 821 { 822 asm volatile (" \ 823 r1 = 0; \ 824 *(u64*)(r10 - 8) = r1; \ 825 r2 = r10; \ 826 r2 += -8; \ 827 r1 = %[map_array_48b] ll; \ 828 call %[bpf_map_lookup_elem]; \ 829 if r0 == 0 goto l0_%=; \ 830 r1 = 49; \ 831 r0 += r1; \ 832 r1 = *(u8*)(r0 + 0); \ 833 l0_%=: r0 = 1; \ 834 exit; \ 835 " : 836 : __imm(bpf_map_lookup_elem), 837 __imm_addr(map_array_48b) 838 : __clobber_all); 839 } 840 841 SEC("socket") 842 __description("map access: value_ptr += known scalar, 3") 843 __failure __msg("invalid access to map value") 844 __failure_unpriv 845 __naked void value_ptr_known_scalar_3(void) 846 { 847 asm volatile (" \ 848 r1 = 0; \ 849 *(u64*)(r10 - 8) = r1; \ 850 r2 = r10; \ 851 r2 += -8; \ 852 r1 = %[map_array_48b] ll; \ 853 call %[bpf_map_lookup_elem]; \ 854 if r0 == 0 goto l0_%=; \ 855 r1 = -1; \ 856 r0 += r1; \ 857 r1 = *(u8*)(r0 + 0); \ 858 l0_%=: r0 = 1; \ 859 exit; \ 860 " : 861 : __imm(bpf_map_lookup_elem), 862 __imm_addr(map_array_48b) 863 : __clobber_all); 864 } 865 866 SEC("socket") 867 __description("map access: value_ptr += known scalar, 4") 868 __success __success_unpriv __retval(1) 869 __naked void value_ptr_known_scalar_4(void) 870 { 871 asm volatile (" \ 872 r1 = 0; \ 873 *(u64*)(r10 - 8) = r1; \ 874 r2 = r10; \ 875 r2 += -8; \ 876 r1 = %[map_array_48b] ll; \ 877 call %[bpf_map_lookup_elem]; \ 878 if r0 == 0 goto l0_%=; \ 879 r1 = 5; \ 880 r0 += r1; \ 881 r1 = -2; \ 882 r0 += r1; \ 883 r1 = -1; \ 884 r0 += r1; \ 885 r1 = *(u8*)(r0 + 0); \ 886 l0_%=: r0 = 1; \ 887 exit; \ 888 " : 889 : __imm(bpf_map_lookup_elem), 890 __imm_addr(map_array_48b) 891 : __clobber_all); 892 } 893 894 SEC("socket") 895 __description("map access: value_ptr += known scalar, 5") 896 __success __success_unpriv __retval(0xabcdef12) 897 __naked void value_ptr_known_scalar_5(void) 898 { 899 asm volatile (" \ 900 r1 = 0; \ 901 *(u64*)(r10 - 8) = r1; \ 902 r2 = r10; \ 903 r2 += -8; \ 904 r1 = %[map_array_48b] ll; \ 905 call %[bpf_map_lookup_elem]; \ 906 if r0 == 0 goto l0_%=; \ 907 r1 = %[__imm_0]; \ 908 r1 += r0; \ 909 r0 = *(u32*)(r1 + 0); \ 910 l0_%=: exit; \ 911 " : 912 : __imm(bpf_map_lookup_elem), 913 __imm_addr(map_array_48b), 914 __imm_const(__imm_0, (6 + 1) * sizeof(int)) 915 : __clobber_all); 916 } 917 918 SEC("socket") 919 __description("map access: value_ptr += known scalar, 6") 920 __success __success_unpriv __retval(0xabcdef12) 921 __naked void value_ptr_known_scalar_6(void) 922 { 923 asm volatile (" \ 924 r1 = 0; \ 925 *(u64*)(r10 - 8) = r1; \ 926 r2 = r10; \ 927 r2 += -8; \ 928 r1 = %[map_array_48b] ll; \ 929 call %[bpf_map_lookup_elem]; \ 930 if r0 == 0 goto l0_%=; \ 931 r1 = %[__imm_0]; \ 932 r0 += r1; \ 933 r1 = %[__imm_1]; \ 934 r0 += r1; \ 935 r0 = *(u32*)(r0 + 0); \ 936 l0_%=: exit; \ 937 " : 938 : __imm(bpf_map_lookup_elem), 939 __imm_addr(map_array_48b), 940 __imm_const(__imm_0, (3 + 1) * sizeof(int)), 941 __imm_const(__imm_1, 3 * sizeof(int)) 942 : __clobber_all); 943 } 944 945 SEC("socket") 946 __description("map access: value_ptr += N, value_ptr -= N known scalar") 947 __success __success_unpriv __retval(0x12345678) 948 __naked void value_ptr_n_known_scalar(void) 949 { 950 asm volatile (" \ 951 r1 = 0; \ 952 *(u64*)(r10 - 8) = r1; \ 953 r2 = r10; \ 954 r2 += -8; \ 955 r1 = %[map_array_48b] ll; \ 956 call %[bpf_map_lookup_elem]; \ 957 if r0 == 0 goto l0_%=; \ 958 w1 = 0x12345678; \ 959 *(u32*)(r0 + 0) = r1; \ 960 r0 += 2; \ 961 r1 = 2; \ 962 r0 -= r1; \ 963 r0 = *(u32*)(r0 + 0); \ 964 l0_%=: exit; \ 965 " : 966 : __imm(bpf_map_lookup_elem), 967 __imm_addr(map_array_48b) 968 : __clobber_all); 969 } 970 971 SEC("socket") 972 __description("map access: unknown scalar += value_ptr, 1") 973 __success __success_unpriv __retval(1) 974 __naked void unknown_scalar_value_ptr_1(void) 975 { 976 asm volatile (" \ 977 r1 = 0; \ 978 *(u64*)(r10 - 8) = r1; \ 979 r2 = r10; \ 980 r2 += -8; \ 981 r1 = %[map_array_48b] ll; \ 982 call %[bpf_map_lookup_elem]; \ 983 if r0 == 0 goto l0_%=; \ 984 r1 = *(u8*)(r0 + 0); \ 985 r1 &= 0xf; \ 986 r1 += r0; \ 987 r0 = *(u8*)(r1 + 0); \ 988 l0_%=: r0 = 1; \ 989 exit; \ 990 " : 991 : __imm(bpf_map_lookup_elem), 992 __imm_addr(map_array_48b) 993 : __clobber_all); 994 } 995 996 SEC("socket") 997 __description("map access: unknown scalar += value_ptr, 2") 998 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 999 __naked void unknown_scalar_value_ptr_2(void) 1000 { 1001 asm volatile (" \ 1002 r1 = 0; \ 1003 *(u64*)(r10 - 8) = r1; \ 1004 r2 = r10; \ 1005 r2 += -8; \ 1006 r1 = %[map_array_48b] ll; \ 1007 call %[bpf_map_lookup_elem]; \ 1008 if r0 == 0 goto l0_%=; \ 1009 r1 = *(u32*)(r0 + 0); \ 1010 r1 &= 31; \ 1011 r1 += r0; \ 1012 r0 = *(u32*)(r1 + 0); \ 1013 l0_%=: exit; \ 1014 " : 1015 : __imm(bpf_map_lookup_elem), 1016 __imm_addr(map_array_48b) 1017 : __clobber_all); 1018 } 1019 1020 SEC("socket") 1021 __description("map access: unknown scalar += value_ptr, 3") 1022 __success __failure_unpriv 1023 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 1024 __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 1025 __naked void unknown_scalar_value_ptr_3(void) 1026 { 1027 asm volatile (" \ 1028 r1 = 0; \ 1029 *(u64*)(r10 - 8) = r1; \ 1030 r2 = r10; \ 1031 r2 += -8; \ 1032 r1 = %[map_array_48b] ll; \ 1033 call %[bpf_map_lookup_elem]; \ 1034 if r0 == 0 goto l0_%=; \ 1035 r1 = -1; \ 1036 r0 += r1; \ 1037 r1 = 1; \ 1038 r0 += r1; \ 1039 r1 = *(u32*)(r0 + 0); \ 1040 r1 &= 31; \ 1041 r1 += r0; \ 1042 r0 = *(u32*)(r1 + 0); \ 1043 l0_%=: exit; \ 1044 " : 1045 : __imm(bpf_map_lookup_elem), 1046 __imm_addr(map_array_48b) 1047 : __clobber_all); 1048 } 1049 1050 SEC("socket") 1051 __description("map access: unknown scalar += value_ptr, 4") 1052 __failure __msg("R1 max value is outside of the allowed memory range") 1053 __msg_unpriv("R1 pointer arithmetic of map value goes out of range") 1054 __flag(BPF_F_ANY_ALIGNMENT) 1055 __naked void unknown_scalar_value_ptr_4(void) 1056 { 1057 asm volatile (" \ 1058 r1 = 0; \ 1059 *(u64*)(r10 - 8) = r1; \ 1060 r2 = r10; \ 1061 r2 += -8; \ 1062 r1 = %[map_array_48b] ll; \ 1063 call %[bpf_map_lookup_elem]; \ 1064 if r0 == 0 goto l0_%=; \ 1065 r1 = 19; \ 1066 r0 += r1; \ 1067 r1 = *(u32*)(r0 + 0); \ 1068 r1 &= 31; \ 1069 r1 += r0; \ 1070 r0 = *(u32*)(r1 + 0); \ 1071 l0_%=: exit; \ 1072 " : 1073 : __imm(bpf_map_lookup_elem), 1074 __imm_addr(map_array_48b) 1075 : __clobber_all); 1076 } 1077 1078 SEC("socket") 1079 __description("map access: value_ptr += unknown scalar, 1") 1080 __success __success_unpriv __retval(1) 1081 __naked void value_ptr_unknown_scalar_1(void) 1082 { 1083 asm volatile (" \ 1084 r1 = 0; \ 1085 *(u64*)(r10 - 8) = r1; \ 1086 r2 = r10; \ 1087 r2 += -8; \ 1088 r1 = %[map_array_48b] ll; \ 1089 call %[bpf_map_lookup_elem]; \ 1090 if r0 == 0 goto l0_%=; \ 1091 r1 = *(u8*)(r0 + 0); \ 1092 r1 &= 0xf; \ 1093 r0 += r1; \ 1094 r1 = *(u8*)(r0 + 0); \ 1095 l0_%=: r0 = 1; \ 1096 exit; \ 1097 " : 1098 : __imm(bpf_map_lookup_elem), 1099 __imm_addr(map_array_48b) 1100 : __clobber_all); 1101 } 1102 1103 SEC("socket") 1104 __description("map access: value_ptr += unknown scalar, 2") 1105 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 1106 __naked void value_ptr_unknown_scalar_2_1(void) 1107 { 1108 asm volatile (" \ 1109 r1 = 0; \ 1110 *(u64*)(r10 - 8) = r1; \ 1111 r2 = r10; \ 1112 r2 += -8; \ 1113 r1 = %[map_array_48b] ll; \ 1114 call %[bpf_map_lookup_elem]; \ 1115 if r0 == 0 goto l0_%=; \ 1116 r1 = *(u32*)(r0 + 0); \ 1117 r1 &= 31; \ 1118 r0 += r1; \ 1119 r0 = *(u32*)(r0 + 0); \ 1120 l0_%=: exit; \ 1121 " : 1122 : __imm(bpf_map_lookup_elem), 1123 __imm_addr(map_array_48b) 1124 : __clobber_all); 1125 } 1126 1127 SEC("socket") 1128 __description("map access: value_ptr += unknown scalar, 3") 1129 __success __success_unpriv __retval(1) 1130 __naked void value_ptr_unknown_scalar_3(void) 1131 { 1132 asm volatile (" \ 1133 r1 = 0; \ 1134 *(u64*)(r10 - 8) = r1; \ 1135 r2 = r10; \ 1136 r2 += -8; \ 1137 r1 = %[map_array_48b] ll; \ 1138 call %[bpf_map_lookup_elem]; \ 1139 if r0 == 0 goto l0_%=; \ 1140 r1 = *(u64*)(r0 + 0); \ 1141 r2 = *(u64*)(r0 + 8); \ 1142 r3 = *(u64*)(r0 + 16); \ 1143 r1 &= 0xf; \ 1144 r3 &= 1; \ 1145 r3 |= 1; \ 1146 if r2 > r3 goto l0_%=; \ 1147 r0 += r3; \ 1148 r0 = *(u8*)(r0 + 0); \ 1149 r0 = 1; \ 1150 l1_%=: exit; \ 1151 l0_%=: r0 = 2; \ 1152 goto l1_%=; \ 1153 " : 1154 : __imm(bpf_map_lookup_elem), 1155 __imm_addr(map_array_48b) 1156 : __clobber_all); 1157 } 1158 1159 SEC("socket") 1160 __description("map access: value_ptr += value_ptr") 1161 __failure __msg("R0 pointer += pointer prohibited") 1162 __failure_unpriv 1163 __naked void access_value_ptr_value_ptr_1(void) 1164 { 1165 asm volatile (" \ 1166 r1 = 0; \ 1167 *(u64*)(r10 - 8) = r1; \ 1168 r2 = r10; \ 1169 r2 += -8; \ 1170 r1 = %[map_array_48b] ll; \ 1171 call %[bpf_map_lookup_elem]; \ 1172 if r0 == 0 goto l0_%=; \ 1173 r0 += r0; \ 1174 r1 = *(u8*)(r0 + 0); \ 1175 l0_%=: r0 = 1; \ 1176 exit; \ 1177 " : 1178 : __imm(bpf_map_lookup_elem), 1179 __imm_addr(map_array_48b) 1180 : __clobber_all); 1181 } 1182 1183 SEC("socket") 1184 __description("map access: known scalar -= value_ptr") 1185 __failure __msg("R1 tried to subtract pointer from scalar") 1186 __failure_unpriv 1187 __naked void access_known_scalar_value_ptr_2(void) 1188 { 1189 asm volatile (" \ 1190 r1 = 0; \ 1191 *(u64*)(r10 - 8) = r1; \ 1192 r2 = r10; \ 1193 r2 += -8; \ 1194 r1 = %[map_array_48b] ll; \ 1195 call %[bpf_map_lookup_elem]; \ 1196 if r0 == 0 goto l0_%=; \ 1197 r1 = 4; \ 1198 r1 -= r0; \ 1199 r0 = *(u8*)(r1 + 0); \ 1200 l0_%=: r0 = 1; \ 1201 exit; \ 1202 " : 1203 : __imm(bpf_map_lookup_elem), 1204 __imm_addr(map_array_48b) 1205 : __clobber_all); 1206 } 1207 1208 SEC("socket") 1209 __description("map access: value_ptr -= known scalar") 1210 __failure __msg("R0 min value is outside of the allowed memory range") 1211 __failure_unpriv 1212 __naked void access_value_ptr_known_scalar(void) 1213 { 1214 asm volatile (" \ 1215 r1 = 0; \ 1216 *(u64*)(r10 - 8) = r1; \ 1217 r2 = r10; \ 1218 r2 += -8; \ 1219 r1 = %[map_array_48b] ll; \ 1220 call %[bpf_map_lookup_elem]; \ 1221 if r0 == 0 goto l0_%=; \ 1222 r1 = 4; \ 1223 r0 -= r1; \ 1224 r1 = *(u8*)(r0 + 0); \ 1225 l0_%=: r0 = 1; \ 1226 exit; \ 1227 " : 1228 : __imm(bpf_map_lookup_elem), 1229 __imm_addr(map_array_48b) 1230 : __clobber_all); 1231 } 1232 1233 SEC("socket") 1234 __description("map access: value_ptr -= known scalar, 2") 1235 __success __success_unpriv __retval(1) 1236 __naked void value_ptr_known_scalar_2_2(void) 1237 { 1238 asm volatile (" \ 1239 r1 = 0; \ 1240 *(u64*)(r10 - 8) = r1; \ 1241 r2 = r10; \ 1242 r2 += -8; \ 1243 r1 = %[map_array_48b] ll; \ 1244 call %[bpf_map_lookup_elem]; \ 1245 if r0 == 0 goto l0_%=; \ 1246 r1 = 6; \ 1247 r2 = 4; \ 1248 r0 += r1; \ 1249 r0 -= r2; \ 1250 r1 = *(u8*)(r0 + 0); \ 1251 l0_%=: r0 = 1; \ 1252 exit; \ 1253 " : 1254 : __imm(bpf_map_lookup_elem), 1255 __imm_addr(map_array_48b) 1256 : __clobber_all); 1257 } 1258 1259 SEC("socket") 1260 __description("map access: unknown scalar -= value_ptr") 1261 __failure __msg("R1 tried to subtract pointer from scalar") 1262 __failure_unpriv 1263 __naked void access_unknown_scalar_value_ptr(void) 1264 { 1265 asm volatile (" \ 1266 r1 = 0; \ 1267 *(u64*)(r10 - 8) = r1; \ 1268 r2 = r10; \ 1269 r2 += -8; \ 1270 r1 = %[map_array_48b] ll; \ 1271 call %[bpf_map_lookup_elem]; \ 1272 if r0 == 0 goto l0_%=; \ 1273 r1 = *(u8*)(r0 + 0); \ 1274 r1 &= 0xf; \ 1275 r1 -= r0; \ 1276 r0 = *(u8*)(r1 + 0); \ 1277 l0_%=: r0 = 1; \ 1278 exit; \ 1279 " : 1280 : __imm(bpf_map_lookup_elem), 1281 __imm_addr(map_array_48b) 1282 : __clobber_all); 1283 } 1284 1285 SEC("socket") 1286 __description("map access: value_ptr -= unknown scalar") 1287 __failure __msg("R0 min value is negative") 1288 __failure_unpriv 1289 __naked void access_value_ptr_unknown_scalar(void) 1290 { 1291 asm volatile (" \ 1292 r1 = 0; \ 1293 *(u64*)(r10 - 8) = r1; \ 1294 r2 = r10; \ 1295 r2 += -8; \ 1296 r1 = %[map_array_48b] ll; \ 1297 call %[bpf_map_lookup_elem]; \ 1298 if r0 == 0 goto l0_%=; \ 1299 r1 = *(u8*)(r0 + 0); \ 1300 r1 &= 0xf; \ 1301 r0 -= r1; \ 1302 r1 = *(u8*)(r0 + 0); \ 1303 l0_%=: r0 = 1; \ 1304 exit; \ 1305 " : 1306 : __imm(bpf_map_lookup_elem), 1307 __imm_addr(map_array_48b) 1308 : __clobber_all); 1309 } 1310 1311 SEC("socket") 1312 __description("map access: value_ptr -= unknown scalar, 2") 1313 __success __success_unpriv 1314 __retval(1) 1315 #ifdef SPEC_V1 1316 __xlated_unpriv("r1 &= 7") 1317 __xlated_unpriv("nospec") /* inserted to prevent `R0 pointer arithmetic of map value goes out of range` */ 1318 __xlated_unpriv("r0 -= r1") 1319 #endif 1320 __naked void value_ptr_unknown_scalar_2_2(void) 1321 { 1322 asm volatile (" \ 1323 r1 = 0; \ 1324 *(u64*)(r10 - 8) = r1; \ 1325 r2 = r10; \ 1326 r2 += -8; \ 1327 r1 = %[map_array_48b] ll; \ 1328 call %[bpf_map_lookup_elem]; \ 1329 if r0 == 0 goto l0_%=; \ 1330 r1 = *(u8*)(r0 + 0); \ 1331 r1 &= 0xf; \ 1332 r1 |= 0x7; \ 1333 r0 += r1; \ 1334 r1 = *(u8*)(r0 + 0); \ 1335 r1 &= 0x7; \ 1336 r0 -= r1; \ 1337 r1 = *(u8*)(r0 + 0); \ 1338 l0_%=: r0 = 1; \ 1339 exit; \ 1340 " : 1341 : __imm(bpf_map_lookup_elem), 1342 __imm_addr(map_array_48b) 1343 : __clobber_all); 1344 } 1345 1346 SEC("socket") 1347 __description("map access: value_ptr -= value_ptr") 1348 __failure __msg("R0 invalid mem access 'scalar'") 1349 __msg_unpriv("R0 pointer -= pointer prohibited") 1350 __naked void access_value_ptr_value_ptr_2(void) 1351 { 1352 asm volatile (" \ 1353 r1 = 0; \ 1354 *(u64*)(r10 - 8) = r1; \ 1355 r2 = r10; \ 1356 r2 += -8; \ 1357 r1 = %[map_array_48b] ll; \ 1358 call %[bpf_map_lookup_elem]; \ 1359 if r0 == 0 goto l0_%=; \ 1360 r0 -= r0; \ 1361 r1 = *(u8*)(r0 + 0); \ 1362 l0_%=: r0 = 1; \ 1363 exit; \ 1364 " : 1365 : __imm(bpf_map_lookup_elem), 1366 __imm_addr(map_array_48b) 1367 : __clobber_all); 1368 } 1369 1370 SEC("socket") 1371 __description("map access: trying to leak tainted dst reg") 1372 __failure __msg("math between map_value pointer and 4294967295 is not allowed") 1373 __failure_unpriv 1374 __naked void to_leak_tainted_dst_reg(void) 1375 { 1376 asm volatile (" \ 1377 r0 = 0; \ 1378 r1 = 0; \ 1379 *(u64*)(r10 - 8) = r1; \ 1380 r2 = r10; \ 1381 r2 += -8; \ 1382 r1 = %[map_array_48b] ll; \ 1383 call %[bpf_map_lookup_elem]; \ 1384 if r0 != 0 goto l0_%=; \ 1385 exit; \ 1386 l0_%=: r2 = r0; \ 1387 w1 = 0xFFFFFFFF; \ 1388 w1 = w1; \ 1389 r2 -= r1; \ 1390 *(u64*)(r0 + 0) = r2; \ 1391 r0 = 0; \ 1392 exit; \ 1393 " : 1394 : __imm(bpf_map_lookup_elem), 1395 __imm_addr(map_array_48b) 1396 : __clobber_all); 1397 } 1398 1399 SEC("tc") 1400 __description("32bit pkt_ptr -= scalar") 1401 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 1402 __naked void _32bit_pkt_ptr_scalar(void) 1403 { 1404 asm volatile (" \ 1405 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 1406 r7 = *(u32*)(r1 + %[__sk_buff_data]); \ 1407 r6 = r7; \ 1408 r6 += 40; \ 1409 if r6 > r8 goto l0_%=; \ 1410 w4 = w7; \ 1411 w6 -= w4; \ 1412 l0_%=: r0 = 0; \ 1413 exit; \ 1414 " : 1415 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 1416 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 1417 : __clobber_all); 1418 } 1419 1420 SEC("tc") 1421 __description("32bit scalar -= pkt_ptr") 1422 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 1423 __naked void _32bit_scalar_pkt_ptr(void) 1424 { 1425 asm volatile (" \ 1426 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 1427 r7 = *(u32*)(r1 + %[__sk_buff_data]); \ 1428 r6 = r7; \ 1429 r6 += 40; \ 1430 if r6 > r8 goto l0_%=; \ 1431 w4 = w6; \ 1432 w4 -= w7; \ 1433 l0_%=: r0 = 0; \ 1434 exit; \ 1435 " : 1436 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 1437 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 1438 : __clobber_all); 1439 } 1440 1441 char _license[] SEC("license") = "GPL"; 1442