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 negative") 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 negative") 687 __naked void lower_oob_arith_test_1(void) 688 { 689 asm volatile (" \ 690 r1 = 0; \ 691 *(u64*)(r10 - 8) = r1; \ 692 r2 = r10; \ 693 r2 += -8; \ 694 r1 = %[map_array_48b] ll; \ 695 call %[bpf_map_lookup_elem]; \ 696 if r0 == 0 goto l0_%=; \ 697 r1 = 47; \ 698 r0 += r1; \ 699 r1 = 48; \ 700 r0 -= r1; \ 701 r0 = *(u8*)(r0 + 0); \ 702 l0_%=: r0 = 1; \ 703 exit; \ 704 " : 705 : __imm(bpf_map_lookup_elem), 706 __imm_addr(map_array_48b) 707 : __clobber_all); 708 } 709 710 SEC("socket") 711 __description("map access: value_ptr -= known scalar, lower oob arith, test 2") 712 __success __failure_unpriv 713 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 714 __retval(1) 715 __naked void lower_oob_arith_test_2(void) 716 { 717 asm volatile (" \ 718 r1 = 0; \ 719 *(u64*)(r10 - 8) = r1; \ 720 r2 = r10; \ 721 r2 += -8; \ 722 r1 = %[map_array_48b] ll; \ 723 call %[bpf_map_lookup_elem]; \ 724 if r0 == 0 goto l0_%=; \ 725 r1 = 47; \ 726 r0 += r1; \ 727 r1 = 48; \ 728 r0 -= r1; \ 729 r1 = 1; \ 730 r0 += r1; \ 731 r0 = *(u8*)(r0 + 0); \ 732 l0_%=: r0 = 1; \ 733 exit; \ 734 " : 735 : __imm(bpf_map_lookup_elem), 736 __imm_addr(map_array_48b) 737 : __clobber_all); 738 } 739 740 SEC("socket") 741 __description("map access: value_ptr -= known scalar, lower oob arith, test 3") 742 __success __success_unpriv __retval(1) 743 __naked void lower_oob_arith_test_3(void) 744 { 745 asm volatile (" \ 746 r1 = 0; \ 747 *(u64*)(r10 - 8) = r1; \ 748 r2 = r10; \ 749 r2 += -8; \ 750 r1 = %[map_array_48b] ll; \ 751 call %[bpf_map_lookup_elem]; \ 752 if r0 == 0 goto l0_%=; \ 753 r1 = 47; \ 754 r0 += r1; \ 755 r1 = 47; \ 756 r0 -= r1; \ 757 r0 = *(u8*)(r0 + 0); \ 758 l0_%=: r0 = 1; \ 759 exit; \ 760 " : 761 : __imm(bpf_map_lookup_elem), 762 __imm_addr(map_array_48b) 763 : __clobber_all); 764 } 765 766 SEC("socket") 767 __description("map access: known scalar += value_ptr") 768 __success __success_unpriv __retval(1) 769 __naked void access_known_scalar_value_ptr_1(void) 770 { 771 asm volatile (" \ 772 r1 = 0; \ 773 *(u64*)(r10 - 8) = r1; \ 774 r2 = r10; \ 775 r2 += -8; \ 776 r1 = %[map_array_48b] ll; \ 777 call %[bpf_map_lookup_elem]; \ 778 if r0 == 0 goto l0_%=; \ 779 r1 = 4; \ 780 r1 += r0; \ 781 r0 = *(u8*)(r1 + 0); \ 782 l0_%=: r0 = 1; \ 783 exit; \ 784 " : 785 : __imm(bpf_map_lookup_elem), 786 __imm_addr(map_array_48b) 787 : __clobber_all); 788 } 789 790 SEC("socket") 791 __description("map access: value_ptr += known scalar, 1") 792 __success __success_unpriv __retval(1) 793 __naked void value_ptr_known_scalar_1(void) 794 { 795 asm volatile (" \ 796 r1 = 0; \ 797 *(u64*)(r10 - 8) = r1; \ 798 r2 = r10; \ 799 r2 += -8; \ 800 r1 = %[map_array_48b] ll; \ 801 call %[bpf_map_lookup_elem]; \ 802 if r0 == 0 goto l0_%=; \ 803 r1 = 4; \ 804 r0 += r1; \ 805 r1 = *(u8*)(r0 + 0); \ 806 l0_%=: r0 = 1; \ 807 exit; \ 808 " : 809 : __imm(bpf_map_lookup_elem), 810 __imm_addr(map_array_48b) 811 : __clobber_all); 812 } 813 814 SEC("socket") 815 __description("map access: value_ptr += known scalar, 2") 816 __failure __msg("invalid access to map value") 817 __failure_unpriv 818 __naked void value_ptr_known_scalar_2_1(void) 819 { 820 asm volatile (" \ 821 r1 = 0; \ 822 *(u64*)(r10 - 8) = r1; \ 823 r2 = r10; \ 824 r2 += -8; \ 825 r1 = %[map_array_48b] ll; \ 826 call %[bpf_map_lookup_elem]; \ 827 if r0 == 0 goto l0_%=; \ 828 r1 = 49; \ 829 r0 += r1; \ 830 r1 = *(u8*)(r0 + 0); \ 831 l0_%=: r0 = 1; \ 832 exit; \ 833 " : 834 : __imm(bpf_map_lookup_elem), 835 __imm_addr(map_array_48b) 836 : __clobber_all); 837 } 838 839 SEC("socket") 840 __description("map access: value_ptr += known scalar, 3") 841 __failure __msg("R0 min value is negative") 842 __failure_unpriv 843 __naked void value_ptr_known_scalar_3(void) 844 { 845 asm volatile (" \ 846 r1 = 0; \ 847 *(u64*)(r10 - 8) = r1; \ 848 r2 = r10; \ 849 r2 += -8; \ 850 r1 = %[map_array_48b] ll; \ 851 call %[bpf_map_lookup_elem]; \ 852 if r0 == 0 goto l0_%=; \ 853 r1 = -1; \ 854 r0 += r1; \ 855 r1 = *(u8*)(r0 + 0); \ 856 l0_%=: r0 = 1; \ 857 exit; \ 858 " : 859 : __imm(bpf_map_lookup_elem), 860 __imm_addr(map_array_48b) 861 : __clobber_all); 862 } 863 864 SEC("socket") 865 __description("map access: value_ptr += known scalar, 4") 866 __success __success_unpriv __retval(1) 867 __naked void value_ptr_known_scalar_4(void) 868 { 869 asm volatile (" \ 870 r1 = 0; \ 871 *(u64*)(r10 - 8) = r1; \ 872 r2 = r10; \ 873 r2 += -8; \ 874 r1 = %[map_array_48b] ll; \ 875 call %[bpf_map_lookup_elem]; \ 876 if r0 == 0 goto l0_%=; \ 877 r1 = 5; \ 878 r0 += r1; \ 879 r1 = -2; \ 880 r0 += r1; \ 881 r1 = -1; \ 882 r0 += r1; \ 883 r1 = *(u8*)(r0 + 0); \ 884 l0_%=: r0 = 1; \ 885 exit; \ 886 " : 887 : __imm(bpf_map_lookup_elem), 888 __imm_addr(map_array_48b) 889 : __clobber_all); 890 } 891 892 SEC("socket") 893 __description("map access: value_ptr += known scalar, 5") 894 __success __success_unpriv __retval(0xabcdef12) 895 __naked void value_ptr_known_scalar_5(void) 896 { 897 asm volatile (" \ 898 r1 = 0; \ 899 *(u64*)(r10 - 8) = r1; \ 900 r2 = r10; \ 901 r2 += -8; \ 902 r1 = %[map_array_48b] ll; \ 903 call %[bpf_map_lookup_elem]; \ 904 if r0 == 0 goto l0_%=; \ 905 r1 = %[__imm_0]; \ 906 r1 += r0; \ 907 r0 = *(u32*)(r1 + 0); \ 908 l0_%=: exit; \ 909 " : 910 : __imm(bpf_map_lookup_elem), 911 __imm_addr(map_array_48b), 912 __imm_const(__imm_0, (6 + 1) * sizeof(int)) 913 : __clobber_all); 914 } 915 916 SEC("socket") 917 __description("map access: value_ptr += known scalar, 6") 918 __success __success_unpriv __retval(0xabcdef12) 919 __naked void value_ptr_known_scalar_6(void) 920 { 921 asm volatile (" \ 922 r1 = 0; \ 923 *(u64*)(r10 - 8) = r1; \ 924 r2 = r10; \ 925 r2 += -8; \ 926 r1 = %[map_array_48b] ll; \ 927 call %[bpf_map_lookup_elem]; \ 928 if r0 == 0 goto l0_%=; \ 929 r1 = %[__imm_0]; \ 930 r0 += r1; \ 931 r1 = %[__imm_1]; \ 932 r0 += r1; \ 933 r0 = *(u32*)(r0 + 0); \ 934 l0_%=: exit; \ 935 " : 936 : __imm(bpf_map_lookup_elem), 937 __imm_addr(map_array_48b), 938 __imm_const(__imm_0, (3 + 1) * sizeof(int)), 939 __imm_const(__imm_1, 3 * sizeof(int)) 940 : __clobber_all); 941 } 942 943 SEC("socket") 944 __description("map access: value_ptr += N, value_ptr -= N known scalar") 945 __success __success_unpriv __retval(0x12345678) 946 __naked void value_ptr_n_known_scalar(void) 947 { 948 asm volatile (" \ 949 r1 = 0; \ 950 *(u64*)(r10 - 8) = r1; \ 951 r2 = r10; \ 952 r2 += -8; \ 953 r1 = %[map_array_48b] ll; \ 954 call %[bpf_map_lookup_elem]; \ 955 if r0 == 0 goto l0_%=; \ 956 w1 = 0x12345678; \ 957 *(u32*)(r0 + 0) = r1; \ 958 r0 += 2; \ 959 r1 = 2; \ 960 r0 -= r1; \ 961 r0 = *(u32*)(r0 + 0); \ 962 l0_%=: exit; \ 963 " : 964 : __imm(bpf_map_lookup_elem), 965 __imm_addr(map_array_48b) 966 : __clobber_all); 967 } 968 969 SEC("socket") 970 __description("map access: unknown scalar += value_ptr, 1") 971 __success __success_unpriv __retval(1) 972 __naked void unknown_scalar_value_ptr_1(void) 973 { 974 asm volatile (" \ 975 r1 = 0; \ 976 *(u64*)(r10 - 8) = r1; \ 977 r2 = r10; \ 978 r2 += -8; \ 979 r1 = %[map_array_48b] ll; \ 980 call %[bpf_map_lookup_elem]; \ 981 if r0 == 0 goto l0_%=; \ 982 r1 = *(u8*)(r0 + 0); \ 983 r1 &= 0xf; \ 984 r1 += r0; \ 985 r0 = *(u8*)(r1 + 0); \ 986 l0_%=: r0 = 1; \ 987 exit; \ 988 " : 989 : __imm(bpf_map_lookup_elem), 990 __imm_addr(map_array_48b) 991 : __clobber_all); 992 } 993 994 SEC("socket") 995 __description("map access: unknown scalar += value_ptr, 2") 996 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 997 __naked void unknown_scalar_value_ptr_2(void) 998 { 999 asm volatile (" \ 1000 r1 = 0; \ 1001 *(u64*)(r10 - 8) = r1; \ 1002 r2 = r10; \ 1003 r2 += -8; \ 1004 r1 = %[map_array_48b] ll; \ 1005 call %[bpf_map_lookup_elem]; \ 1006 if r0 == 0 goto l0_%=; \ 1007 r1 = *(u32*)(r0 + 0); \ 1008 r1 &= 31; \ 1009 r1 += r0; \ 1010 r0 = *(u32*)(r1 + 0); \ 1011 l0_%=: exit; \ 1012 " : 1013 : __imm(bpf_map_lookup_elem), 1014 __imm_addr(map_array_48b) 1015 : __clobber_all); 1016 } 1017 1018 SEC("socket") 1019 __description("map access: unknown scalar += value_ptr, 3") 1020 __success __failure_unpriv 1021 __msg_unpriv("R0 pointer arithmetic of map value goes out of range") 1022 __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 1023 __naked void unknown_scalar_value_ptr_3(void) 1024 { 1025 asm volatile (" \ 1026 r1 = 0; \ 1027 *(u64*)(r10 - 8) = r1; \ 1028 r2 = r10; \ 1029 r2 += -8; \ 1030 r1 = %[map_array_48b] ll; \ 1031 call %[bpf_map_lookup_elem]; \ 1032 if r0 == 0 goto l0_%=; \ 1033 r1 = -1; \ 1034 r0 += r1; \ 1035 r1 = 1; \ 1036 r0 += r1; \ 1037 r1 = *(u32*)(r0 + 0); \ 1038 r1 &= 31; \ 1039 r1 += r0; \ 1040 r0 = *(u32*)(r1 + 0); \ 1041 l0_%=: exit; \ 1042 " : 1043 : __imm(bpf_map_lookup_elem), 1044 __imm_addr(map_array_48b) 1045 : __clobber_all); 1046 } 1047 1048 SEC("socket") 1049 __description("map access: unknown scalar += value_ptr, 4") 1050 __failure __msg("R1 max value is outside of the allowed memory range") 1051 __msg_unpriv("R1 pointer arithmetic of map value goes out of range") 1052 __flag(BPF_F_ANY_ALIGNMENT) 1053 __naked void unknown_scalar_value_ptr_4(void) 1054 { 1055 asm volatile (" \ 1056 r1 = 0; \ 1057 *(u64*)(r10 - 8) = r1; \ 1058 r2 = r10; \ 1059 r2 += -8; \ 1060 r1 = %[map_array_48b] ll; \ 1061 call %[bpf_map_lookup_elem]; \ 1062 if r0 == 0 goto l0_%=; \ 1063 r1 = 19; \ 1064 r0 += r1; \ 1065 r1 = *(u32*)(r0 + 0); \ 1066 r1 &= 31; \ 1067 r1 += r0; \ 1068 r0 = *(u32*)(r1 + 0); \ 1069 l0_%=: exit; \ 1070 " : 1071 : __imm(bpf_map_lookup_elem), 1072 __imm_addr(map_array_48b) 1073 : __clobber_all); 1074 } 1075 1076 SEC("socket") 1077 __description("map access: value_ptr += unknown scalar, 1") 1078 __success __success_unpriv __retval(1) 1079 __naked void value_ptr_unknown_scalar_1(void) 1080 { 1081 asm volatile (" \ 1082 r1 = 0; \ 1083 *(u64*)(r10 - 8) = r1; \ 1084 r2 = r10; \ 1085 r2 += -8; \ 1086 r1 = %[map_array_48b] ll; \ 1087 call %[bpf_map_lookup_elem]; \ 1088 if r0 == 0 goto l0_%=; \ 1089 r1 = *(u8*)(r0 + 0); \ 1090 r1 &= 0xf; \ 1091 r0 += r1; \ 1092 r1 = *(u8*)(r0 + 0); \ 1093 l0_%=: r0 = 1; \ 1094 exit; \ 1095 " : 1096 : __imm(bpf_map_lookup_elem), 1097 __imm_addr(map_array_48b) 1098 : __clobber_all); 1099 } 1100 1101 SEC("socket") 1102 __description("map access: value_ptr += unknown scalar, 2") 1103 __success __success_unpriv __retval(0xabcdef12) __flag(BPF_F_ANY_ALIGNMENT) 1104 __naked void value_ptr_unknown_scalar_2_1(void) 1105 { 1106 asm volatile (" \ 1107 r1 = 0; \ 1108 *(u64*)(r10 - 8) = r1; \ 1109 r2 = r10; \ 1110 r2 += -8; \ 1111 r1 = %[map_array_48b] ll; \ 1112 call %[bpf_map_lookup_elem]; \ 1113 if r0 == 0 goto l0_%=; \ 1114 r1 = *(u32*)(r0 + 0); \ 1115 r1 &= 31; \ 1116 r0 += r1; \ 1117 r0 = *(u32*)(r0 + 0); \ 1118 l0_%=: exit; \ 1119 " : 1120 : __imm(bpf_map_lookup_elem), 1121 __imm_addr(map_array_48b) 1122 : __clobber_all); 1123 } 1124 1125 SEC("socket") 1126 __description("map access: value_ptr += unknown scalar, 3") 1127 __success __success_unpriv __retval(1) 1128 __naked void value_ptr_unknown_scalar_3(void) 1129 { 1130 asm volatile (" \ 1131 r1 = 0; \ 1132 *(u64*)(r10 - 8) = r1; \ 1133 r2 = r10; \ 1134 r2 += -8; \ 1135 r1 = %[map_array_48b] ll; \ 1136 call %[bpf_map_lookup_elem]; \ 1137 if r0 == 0 goto l0_%=; \ 1138 r1 = *(u64*)(r0 + 0); \ 1139 r2 = *(u64*)(r0 + 8); \ 1140 r3 = *(u64*)(r0 + 16); \ 1141 r1 &= 0xf; \ 1142 r3 &= 1; \ 1143 r3 |= 1; \ 1144 if r2 > r3 goto l0_%=; \ 1145 r0 += r3; \ 1146 r0 = *(u8*)(r0 + 0); \ 1147 r0 = 1; \ 1148 l1_%=: exit; \ 1149 l0_%=: r0 = 2; \ 1150 goto l1_%=; \ 1151 " : 1152 : __imm(bpf_map_lookup_elem), 1153 __imm_addr(map_array_48b) 1154 : __clobber_all); 1155 } 1156 1157 SEC("socket") 1158 __description("map access: value_ptr += value_ptr") 1159 __failure __msg("R0 pointer += pointer prohibited") 1160 __failure_unpriv 1161 __naked void access_value_ptr_value_ptr_1(void) 1162 { 1163 asm volatile (" \ 1164 r1 = 0; \ 1165 *(u64*)(r10 - 8) = r1; \ 1166 r2 = r10; \ 1167 r2 += -8; \ 1168 r1 = %[map_array_48b] ll; \ 1169 call %[bpf_map_lookup_elem]; \ 1170 if r0 == 0 goto l0_%=; \ 1171 r0 += r0; \ 1172 r1 = *(u8*)(r0 + 0); \ 1173 l0_%=: r0 = 1; \ 1174 exit; \ 1175 " : 1176 : __imm(bpf_map_lookup_elem), 1177 __imm_addr(map_array_48b) 1178 : __clobber_all); 1179 } 1180 1181 SEC("socket") 1182 __description("map access: known scalar -= value_ptr") 1183 __failure __msg("R1 tried to subtract pointer from scalar") 1184 __failure_unpriv 1185 __naked void access_known_scalar_value_ptr_2(void) 1186 { 1187 asm volatile (" \ 1188 r1 = 0; \ 1189 *(u64*)(r10 - 8) = r1; \ 1190 r2 = r10; \ 1191 r2 += -8; \ 1192 r1 = %[map_array_48b] ll; \ 1193 call %[bpf_map_lookup_elem]; \ 1194 if r0 == 0 goto l0_%=; \ 1195 r1 = 4; \ 1196 r1 -= r0; \ 1197 r0 = *(u8*)(r1 + 0); \ 1198 l0_%=: r0 = 1; \ 1199 exit; \ 1200 " : 1201 : __imm(bpf_map_lookup_elem), 1202 __imm_addr(map_array_48b) 1203 : __clobber_all); 1204 } 1205 1206 SEC("socket") 1207 __description("map access: value_ptr -= known scalar") 1208 __failure __msg("R0 min value is negative") 1209 __failure_unpriv 1210 __naked void access_value_ptr_known_scalar(void) 1211 { 1212 asm volatile (" \ 1213 r1 = 0; \ 1214 *(u64*)(r10 - 8) = r1; \ 1215 r2 = r10; \ 1216 r2 += -8; \ 1217 r1 = %[map_array_48b] ll; \ 1218 call %[bpf_map_lookup_elem]; \ 1219 if r0 == 0 goto l0_%=; \ 1220 r1 = 4; \ 1221 r0 -= r1; \ 1222 r1 = *(u8*)(r0 + 0); \ 1223 l0_%=: r0 = 1; \ 1224 exit; \ 1225 " : 1226 : __imm(bpf_map_lookup_elem), 1227 __imm_addr(map_array_48b) 1228 : __clobber_all); 1229 } 1230 1231 SEC("socket") 1232 __description("map access: value_ptr -= known scalar, 2") 1233 __success __success_unpriv __retval(1) 1234 __naked void value_ptr_known_scalar_2_2(void) 1235 { 1236 asm volatile (" \ 1237 r1 = 0; \ 1238 *(u64*)(r10 - 8) = r1; \ 1239 r2 = r10; \ 1240 r2 += -8; \ 1241 r1 = %[map_array_48b] ll; \ 1242 call %[bpf_map_lookup_elem]; \ 1243 if r0 == 0 goto l0_%=; \ 1244 r1 = 6; \ 1245 r2 = 4; \ 1246 r0 += r1; \ 1247 r0 -= r2; \ 1248 r1 = *(u8*)(r0 + 0); \ 1249 l0_%=: r0 = 1; \ 1250 exit; \ 1251 " : 1252 : __imm(bpf_map_lookup_elem), 1253 __imm_addr(map_array_48b) 1254 : __clobber_all); 1255 } 1256 1257 SEC("socket") 1258 __description("map access: unknown scalar -= value_ptr") 1259 __failure __msg("R1 tried to subtract pointer from scalar") 1260 __failure_unpriv 1261 __naked void access_unknown_scalar_value_ptr(void) 1262 { 1263 asm volatile (" \ 1264 r1 = 0; \ 1265 *(u64*)(r10 - 8) = r1; \ 1266 r2 = r10; \ 1267 r2 += -8; \ 1268 r1 = %[map_array_48b] ll; \ 1269 call %[bpf_map_lookup_elem]; \ 1270 if r0 == 0 goto l0_%=; \ 1271 r1 = *(u8*)(r0 + 0); \ 1272 r1 &= 0xf; \ 1273 r1 -= r0; \ 1274 r0 = *(u8*)(r1 + 0); \ 1275 l0_%=: r0 = 1; \ 1276 exit; \ 1277 " : 1278 : __imm(bpf_map_lookup_elem), 1279 __imm_addr(map_array_48b) 1280 : __clobber_all); 1281 } 1282 1283 SEC("socket") 1284 __description("map access: value_ptr -= unknown scalar") 1285 __failure __msg("R0 min value is negative") 1286 __failure_unpriv 1287 __naked void access_value_ptr_unknown_scalar(void) 1288 { 1289 asm volatile (" \ 1290 r1 = 0; \ 1291 *(u64*)(r10 - 8) = r1; \ 1292 r2 = r10; \ 1293 r2 += -8; \ 1294 r1 = %[map_array_48b] ll; \ 1295 call %[bpf_map_lookup_elem]; \ 1296 if r0 == 0 goto l0_%=; \ 1297 r1 = *(u8*)(r0 + 0); \ 1298 r1 &= 0xf; \ 1299 r0 -= r1; \ 1300 r1 = *(u8*)(r0 + 0); \ 1301 l0_%=: r0 = 1; \ 1302 exit; \ 1303 " : 1304 : __imm(bpf_map_lookup_elem), 1305 __imm_addr(map_array_48b) 1306 : __clobber_all); 1307 } 1308 1309 SEC("socket") 1310 __description("map access: value_ptr -= unknown scalar, 2") 1311 __success __success_unpriv 1312 __retval(1) 1313 #ifdef SPEC_V1 1314 __xlated_unpriv("r1 &= 7") 1315 __xlated_unpriv("nospec") /* inserted to prevent `R0 pointer arithmetic of map value goes out of range` */ 1316 __xlated_unpriv("r0 -= r1") 1317 #endif 1318 __naked void value_ptr_unknown_scalar_2_2(void) 1319 { 1320 asm volatile (" \ 1321 r1 = 0; \ 1322 *(u64*)(r10 - 8) = r1; \ 1323 r2 = r10; \ 1324 r2 += -8; \ 1325 r1 = %[map_array_48b] ll; \ 1326 call %[bpf_map_lookup_elem]; \ 1327 if r0 == 0 goto l0_%=; \ 1328 r1 = *(u8*)(r0 + 0); \ 1329 r1 &= 0xf; \ 1330 r1 |= 0x7; \ 1331 r0 += r1; \ 1332 r1 = *(u8*)(r0 + 0); \ 1333 r1 &= 0x7; \ 1334 r0 -= r1; \ 1335 r1 = *(u8*)(r0 + 0); \ 1336 l0_%=: r0 = 1; \ 1337 exit; \ 1338 " : 1339 : __imm(bpf_map_lookup_elem), 1340 __imm_addr(map_array_48b) 1341 : __clobber_all); 1342 } 1343 1344 SEC("socket") 1345 __description("map access: value_ptr -= value_ptr") 1346 __failure __msg("R0 invalid mem access 'scalar'") 1347 __msg_unpriv("R0 pointer -= pointer prohibited") 1348 __naked void access_value_ptr_value_ptr_2(void) 1349 { 1350 asm volatile (" \ 1351 r1 = 0; \ 1352 *(u64*)(r10 - 8) = r1; \ 1353 r2 = r10; \ 1354 r2 += -8; \ 1355 r1 = %[map_array_48b] ll; \ 1356 call %[bpf_map_lookup_elem]; \ 1357 if r0 == 0 goto l0_%=; \ 1358 r0 -= r0; \ 1359 r1 = *(u8*)(r0 + 0); \ 1360 l0_%=: r0 = 1; \ 1361 exit; \ 1362 " : 1363 : __imm(bpf_map_lookup_elem), 1364 __imm_addr(map_array_48b) 1365 : __clobber_all); 1366 } 1367 1368 SEC("socket") 1369 __description("map access: trying to leak tainted dst reg") 1370 __failure __msg("math between map_value pointer and 4294967295 is not allowed") 1371 __failure_unpriv 1372 __naked void to_leak_tainted_dst_reg(void) 1373 { 1374 asm volatile (" \ 1375 r0 = 0; \ 1376 r1 = 0; \ 1377 *(u64*)(r10 - 8) = r1; \ 1378 r2 = r10; \ 1379 r2 += -8; \ 1380 r1 = %[map_array_48b] ll; \ 1381 call %[bpf_map_lookup_elem]; \ 1382 if r0 != 0 goto l0_%=; \ 1383 exit; \ 1384 l0_%=: r2 = r0; \ 1385 w1 = 0xFFFFFFFF; \ 1386 w1 = w1; \ 1387 r2 -= r1; \ 1388 *(u64*)(r0 + 0) = r2; \ 1389 r0 = 0; \ 1390 exit; \ 1391 " : 1392 : __imm(bpf_map_lookup_elem), 1393 __imm_addr(map_array_48b) 1394 : __clobber_all); 1395 } 1396 1397 SEC("tc") 1398 __description("32bit pkt_ptr -= scalar") 1399 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 1400 __naked void _32bit_pkt_ptr_scalar(void) 1401 { 1402 asm volatile (" \ 1403 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 1404 r7 = *(u32*)(r1 + %[__sk_buff_data]); \ 1405 r6 = r7; \ 1406 r6 += 40; \ 1407 if r6 > r8 goto l0_%=; \ 1408 w4 = w7; \ 1409 w6 -= w4; \ 1410 l0_%=: r0 = 0; \ 1411 exit; \ 1412 " : 1413 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 1414 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 1415 : __clobber_all); 1416 } 1417 1418 SEC("tc") 1419 __description("32bit scalar -= pkt_ptr") 1420 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT) 1421 __naked void _32bit_scalar_pkt_ptr(void) 1422 { 1423 asm volatile (" \ 1424 r8 = *(u32*)(r1 + %[__sk_buff_data_end]); \ 1425 r7 = *(u32*)(r1 + %[__sk_buff_data]); \ 1426 r6 = r7; \ 1427 r6 += 40; \ 1428 if r6 > r8 goto l0_%=; \ 1429 w4 = w6; \ 1430 w4 -= w7; \ 1431 l0_%=: r0 = 0; \ 1432 exit; \ 1433 " : 1434 : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)), 1435 __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end)) 1436 : __clobber_all); 1437 } 1438 1439 char _license[] SEC("license") = "GPL"; 1440