1// SPDX-License-Identifier: GPL-2.0 2/* Converted from tools/testing/selftests/bpf/verifier/unpriv.c */ 3 4#include <linux/bpf.h> 5#include <bpf/bpf_helpers.h> 6#include "../../../include/linux/filter.h" 7#include "bpf_misc.h" 8 9#define BPF_SK_LOOKUP(func) \ 10 /* struct bpf_sock_tuple tuple = {} */ \ 11 "r2 = 0;" \ 12 "*(u32*)(r10 - 8) = r2;" \ 13 "*(u64*)(r10 - 16) = r2;" \ 14 "*(u64*)(r10 - 24) = r2;" \ 15 "*(u64*)(r10 - 32) = r2;" \ 16 "*(u64*)(r10 - 40) = r2;" \ 17 "*(u64*)(r10 - 48) = r2;" \ 18 /* sk = func(ctx, &tuple, sizeof tuple, 0, 0) */ \ 19 "r2 = r10;" \ 20 "r2 += -48;" \ 21 "r3 = %[sizeof_bpf_sock_tuple];"\ 22 "r4 = 0;" \ 23 "r5 = 0;" \ 24 "call %[" #func "];" 25 26struct { 27 __uint(type, BPF_MAP_TYPE_HASH); 28 __uint(max_entries, 1); 29 __type(key, long long); 30 __type(value, long long); 31} map_hash_8b SEC(".maps"); 32 33void dummy_prog_42_socket(void); 34void dummy_prog_24_socket(void); 35void dummy_prog_loop1_socket(void); 36 37struct { 38 __uint(type, BPF_MAP_TYPE_PROG_ARRAY); 39 __uint(max_entries, 4); 40 __uint(key_size, sizeof(int)); 41 __array(values, void (void)); 42} map_prog1_socket SEC(".maps") = { 43 .values = { 44 [0] = (void *)&dummy_prog_42_socket, 45 [1] = (void *)&dummy_prog_loop1_socket, 46 [2] = (void *)&dummy_prog_24_socket, 47 }, 48}; 49 50SEC("socket") 51__auxiliary __auxiliary_unpriv 52__naked void dummy_prog_42_socket(void) 53{ 54 asm volatile ("r0 = 42; exit;"); 55} 56 57SEC("socket") 58__auxiliary __auxiliary_unpriv 59__naked void dummy_prog_24_socket(void) 60{ 61 asm volatile ("r0 = 24; exit;"); 62} 63 64SEC("socket") 65__auxiliary __auxiliary_unpriv 66__naked void dummy_prog_loop1_socket(void) 67{ 68 asm volatile (" \ 69 r3 = 1; \ 70 r2 = %[map_prog1_socket] ll; \ 71 call %[bpf_tail_call]; \ 72 r0 = 41; \ 73 exit; \ 74" : 75 : __imm(bpf_tail_call), 76 __imm_addr(map_prog1_socket) 77 : __clobber_all); 78} 79 80SEC("socket") 81__description("unpriv: return pointer") 82__success __failure_unpriv __msg_unpriv("R0 leaks addr") 83__retval(POINTER_VALUE) 84__naked void unpriv_return_pointer(void) 85{ 86 asm volatile (" \ 87 r0 = r10; \ 88 exit; \ 89" ::: __clobber_all); 90} 91 92SEC("socket") 93__description("unpriv: add const to pointer") 94__success __success_unpriv __retval(0) 95__naked void unpriv_add_const_to_pointer(void) 96{ 97 asm volatile (" \ 98 r1 += 8; \ 99 r0 = 0; \ 100 exit; \ 101" ::: __clobber_all); 102} 103 104SEC("socket") 105__description("unpriv: add pointer to pointer") 106__failure __msg("R1 pointer += pointer") 107__failure_unpriv 108__naked void unpriv_add_pointer_to_pointer(void) 109{ 110 asm volatile (" \ 111 r1 += r10; \ 112 r0 = 0; \ 113 exit; \ 114" ::: __clobber_all); 115} 116 117SEC("socket") 118__description("unpriv: neg pointer") 119__success __failure_unpriv __msg_unpriv("R1 pointer arithmetic") 120__retval(0) 121__naked void unpriv_neg_pointer(void) 122{ 123 asm volatile (" \ 124 r1 = -r1; \ 125 r0 = 0; \ 126 exit; \ 127" ::: __clobber_all); 128} 129 130SEC("socket") 131__description("unpriv: cmp pointer with const") 132__success __failure_unpriv __msg_unpriv("R1 pointer comparison") 133__retval(0) 134__naked void unpriv_cmp_pointer_with_const(void) 135{ 136 asm volatile (" \ 137 if r1 == 0 goto l0_%=; \ 138l0_%=: r0 = 0; \ 139 exit; \ 140" ::: __clobber_all); 141} 142 143SEC("socket") 144__description("unpriv: cmp pointer with pointer") 145__success __failure_unpriv __msg_unpriv("R10 pointer comparison") 146__retval(0) 147__naked void unpriv_cmp_pointer_with_pointer(void) 148{ 149 asm volatile (" \ 150 if r1 == r10 goto l0_%=; \ 151l0_%=: r0 = 0; \ 152 exit; \ 153" ::: __clobber_all); 154} 155 156SEC("tracepoint") 157__description("unpriv: check that printk is disallowed") 158__success 159__naked void check_that_printk_is_disallowed(void) 160{ 161 asm volatile (" \ 162 r1 = 0; \ 163 *(u64*)(r10 - 8) = r1; \ 164 r1 = r10; \ 165 r1 += -8; \ 166 r2 = 8; \ 167 r3 = r1; \ 168 call %[bpf_trace_printk]; \ 169 r0 = 0; \ 170 exit; \ 171" : 172 : __imm(bpf_trace_printk) 173 : __clobber_all); 174} 175 176SEC("socket") 177__description("unpriv: pass pointer to helper function") 178__success __failure_unpriv __msg_unpriv("R4 leaks addr") 179__retval(0) 180__naked void pass_pointer_to_helper_function(void) 181{ 182 asm volatile (" \ 183 r1 = 0; \ 184 *(u64*)(r10 - 8) = r1; \ 185 r2 = r10; \ 186 r2 += -8; \ 187 r1 = %[map_hash_8b] ll; \ 188 r3 = r2; \ 189 r4 = r2; \ 190 call %[bpf_map_update_elem]; \ 191 r0 = 0; \ 192 exit; \ 193" : 194 : __imm(bpf_map_update_elem), 195 __imm_addr(map_hash_8b) 196 : __clobber_all); 197} 198 199SEC("socket") 200__description("unpriv: indirectly pass pointer on stack to helper function") 201__success __failure_unpriv 202__msg_unpriv("invalid indirect read from stack R2 off -8+0 size 8") 203__retval(0) 204__naked void on_stack_to_helper_function(void) 205{ 206 asm volatile (" \ 207 *(u64*)(r10 - 8) = r10; \ 208 r2 = r10; \ 209 r2 += -8; \ 210 r1 = %[map_hash_8b] ll; \ 211 call %[bpf_map_lookup_elem]; \ 212 r0 = 0; \ 213 exit; \ 214" : 215 : __imm(bpf_map_lookup_elem), 216 __imm_addr(map_hash_8b) 217 : __clobber_all); 218} 219 220SEC("socket") 221__description("unpriv: mangle pointer on stack 1") 222__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled") 223__retval(0) 224__naked void mangle_pointer_on_stack_1(void) 225{ 226 asm volatile (" \ 227 *(u64*)(r10 - 8) = r10; \ 228 r0 = 0; \ 229 *(u32*)(r10 - 8) = r0; \ 230 r0 = 0; \ 231 exit; \ 232" ::: __clobber_all); 233} 234 235SEC("socket") 236__description("unpriv: mangle pointer on stack 2") 237__success __failure_unpriv __msg_unpriv("attempt to corrupt spilled") 238__retval(0) 239__naked void mangle_pointer_on_stack_2(void) 240{ 241 asm volatile (" \ 242 *(u64*)(r10 - 8) = r10; \ 243 r0 = 0; \ 244 *(u8*)(r10 - 1) = r0; \ 245 r0 = 0; \ 246 exit; \ 247" ::: __clobber_all); 248} 249 250SEC("socket") 251__description("unpriv: read pointer from stack in small chunks") 252__failure __msg("invalid size") 253__failure_unpriv 254__naked void from_stack_in_small_chunks(void) 255{ 256 asm volatile (" \ 257 *(u64*)(r10 - 8) = r10; \ 258 r0 = *(u32*)(r10 - 8); \ 259 r0 = 0; \ 260 exit; \ 261" ::: __clobber_all); 262} 263 264SEC("socket") 265__description("unpriv: write pointer into ctx") 266__failure __msg("invalid bpf_context access") 267__failure_unpriv __msg_unpriv("R1 leaks addr") 268__naked void unpriv_write_pointer_into_ctx(void) 269{ 270 asm volatile (" \ 271 *(u64*)(r1 + 0) = r1; \ 272 r0 = 0; \ 273 exit; \ 274" ::: __clobber_all); 275} 276 277SEC("socket") 278__description("unpriv: spill/fill of ctx") 279__success __success_unpriv __retval(0) 280__naked void unpriv_spill_fill_of_ctx(void) 281{ 282 asm volatile (" \ 283 r6 = r10; \ 284 r6 += -8; \ 285 *(u64*)(r6 + 0) = r1; \ 286 r1 = *(u64*)(r6 + 0); \ 287 r0 = 0; \ 288 exit; \ 289" ::: __clobber_all); 290} 291 292SEC("tc") 293__description("unpriv: spill/fill of ctx 2") 294__success __retval(0) 295__naked void spill_fill_of_ctx_2(void) 296{ 297 asm volatile (" \ 298 r6 = r10; \ 299 r6 += -8; \ 300 *(u64*)(r6 + 0) = r1; \ 301 r1 = *(u64*)(r6 + 0); \ 302 call %[bpf_get_hash_recalc]; \ 303 r0 = 0; \ 304 exit; \ 305" : 306 : __imm(bpf_get_hash_recalc) 307 : __clobber_all); 308} 309 310SEC("tc") 311__description("unpriv: spill/fill of ctx 3") 312__failure __msg("R1 type=fp expected=ctx") 313__naked void spill_fill_of_ctx_3(void) 314{ 315 asm volatile (" \ 316 r6 = r10; \ 317 r6 += -8; \ 318 *(u64*)(r6 + 0) = r1; \ 319 *(u64*)(r6 + 0) = r10; \ 320 r1 = *(u64*)(r6 + 0); \ 321 call %[bpf_get_hash_recalc]; \ 322 exit; \ 323" : 324 : __imm(bpf_get_hash_recalc) 325 : __clobber_all); 326} 327 328SEC("tc") 329__description("unpriv: spill/fill of ctx 4") 330__failure __msg("R1 type=scalar expected=ctx") 331__naked void spill_fill_of_ctx_4(void) 332{ 333 asm volatile (" \ 334 r6 = r10; \ 335 r6 += -8; \ 336 *(u64*)(r6 + 0) = r1; \ 337 r0 = 1; \ 338 lock *(u64 *)(r10 - 8) += r0; \ 339 r1 = *(u64*)(r6 + 0); \ 340 call %[bpf_get_hash_recalc]; \ 341 exit; \ 342" : 343 : __imm(bpf_get_hash_recalc) 344 : __clobber_all); 345} 346 347SEC("tc") 348__description("unpriv: spill/fill of different pointers stx") 349__failure __msg("same insn cannot be used with different pointers") 350__naked void fill_of_different_pointers_stx(void) 351{ 352 asm volatile (" \ 353 r3 = 42; \ 354 r6 = r10; \ 355 r6 += -8; \ 356 if r1 == 0 goto l0_%=; \ 357 r2 = r10; \ 358 r2 += -16; \ 359 *(u64*)(r6 + 0) = r2; \ 360l0_%=: if r1 != 0 goto l1_%=; \ 361 *(u64*)(r6 + 0) = r1; \ 362l1_%=: r1 = *(u64*)(r6 + 0); \ 363 *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 364 r0 = 0; \ 365 exit; \ 366" : 367 : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 368 : __clobber_all); 369} 370 371/* Same as above, but use BPF_ST_MEM to save 42 372 * instead of BPF_STX_MEM. 373 */ 374SEC("tc") 375__description("unpriv: spill/fill of different pointers st") 376__failure __msg("same insn cannot be used with different pointers") 377__naked void fill_of_different_pointers_st(void) 378{ 379 asm volatile (" \ 380 r6 = r10; \ 381 r6 += -8; \ 382 if r1 == 0 goto l0_%=; \ 383 r2 = r10; \ 384 r2 += -16; \ 385 *(u64*)(r6 + 0) = r2; \ 386l0_%=: if r1 != 0 goto l1_%=; \ 387 *(u64*)(r6 + 0) = r1; \ 388l1_%=: r1 = *(u64*)(r6 + 0); \ 389 .8byte %[st_mem]; \ 390 r0 = 0; \ 391 exit; \ 392" : 393 : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 394 __imm_insn(st_mem, 395 BPF_ST_MEM(BPF_W, BPF_REG_1, offsetof(struct __sk_buff, mark), 42)) 396 : __clobber_all); 397} 398 399SEC("tc") 400__description("unpriv: spill/fill of different pointers stx - ctx and sock") 401__failure __msg("type=ctx expected=sock") 402__naked void pointers_stx_ctx_and_sock(void) 403{ 404 asm volatile (" \ 405 r8 = r1; \ 406 /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 407" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 408" r2 = r0; \ 409 /* u64 foo; */ \ 410 /* void *target = &foo; */ \ 411 r6 = r10; \ 412 r6 += -8; \ 413 r1 = r8; \ 414 /* if (skb == NULL) *target = sock; */ \ 415 if r1 == 0 goto l0_%=; \ 416 *(u64*)(r6 + 0) = r2; \ 417l0_%=: /* else *target = skb; */ \ 418 if r1 != 0 goto l1_%=; \ 419 *(u64*)(r6 + 0) = r1; \ 420l1_%=: /* struct __sk_buff *skb = *target; */ \ 421 r1 = *(u64*)(r6 + 0); \ 422 /* skb->mark = 42; */ \ 423 r3 = 42; \ 424 *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 425 /* if (sk) bpf_sk_release(sk) */ \ 426 if r1 == 0 goto l2_%=; \ 427 call %[bpf_sk_release]; \ 428l2_%=: r0 = 0; \ 429 exit; \ 430" : 431 : __imm(bpf_sk_lookup_tcp), 432 __imm(bpf_sk_release), 433 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 434 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 435 : __clobber_all); 436} 437 438SEC("tc") 439__description("unpriv: spill/fill of different pointers stx - leak sock") 440__failure 441//.errstr = "same insn cannot be used with different pointers", 442__msg("Unreleased reference") 443__naked void different_pointers_stx_leak_sock(void) 444{ 445 asm volatile (" \ 446 r8 = r1; \ 447 /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 448" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 449" r2 = r0; \ 450 /* u64 foo; */ \ 451 /* void *target = &foo; */ \ 452 r6 = r10; \ 453 r6 += -8; \ 454 r1 = r8; \ 455 /* if (skb == NULL) *target = sock; */ \ 456 if r1 == 0 goto l0_%=; \ 457 *(u64*)(r6 + 0) = r2; \ 458l0_%=: /* else *target = skb; */ \ 459 if r1 != 0 goto l1_%=; \ 460 *(u64*)(r6 + 0) = r1; \ 461l1_%=: /* struct __sk_buff *skb = *target; */ \ 462 r1 = *(u64*)(r6 + 0); \ 463 /* skb->mark = 42; */ \ 464 r3 = 42; \ 465 *(u32*)(r1 + %[__sk_buff_mark]) = r3; \ 466 exit; \ 467" : 468 : __imm(bpf_sk_lookup_tcp), 469 __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)), 470 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 471 : __clobber_all); 472} 473 474SEC("tc") 475__description("unpriv: spill/fill of different pointers stx - sock and ctx (read)") 476__failure __msg("same insn cannot be used with different pointers") 477__naked void stx_sock_and_ctx_read(void) 478{ 479 asm volatile (" \ 480 r8 = r1; \ 481 /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 482" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 483" r2 = r0; \ 484 /* u64 foo; */ \ 485 /* void *target = &foo; */ \ 486 r6 = r10; \ 487 r6 += -8; \ 488 r1 = r8; \ 489 /* if (skb) *target = skb */ \ 490 if r1 == 0 goto l0_%=; \ 491 *(u64*)(r6 + 0) = r1; \ 492l0_%=: /* else *target = sock */ \ 493 if r1 != 0 goto l1_%=; \ 494 *(u64*)(r6 + 0) = r2; \ 495l1_%=: /* struct bpf_sock *sk = *target; */ \ 496 r1 = *(u64*)(r6 + 0); \ 497 /* if (sk) u32 foo = sk->mark; bpf_sk_release(sk); */\ 498 if r1 == 0 goto l2_%=; \ 499 r3 = *(u32*)(r1 + %[bpf_sock_mark]); \ 500 call %[bpf_sk_release]; \ 501l2_%=: r0 = 0; \ 502 exit; \ 503" : 504 : __imm(bpf_sk_lookup_tcp), 505 __imm(bpf_sk_release), 506 __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), 507 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 508 : __clobber_all); 509} 510 511SEC("tc") 512__description("unpriv: spill/fill of different pointers stx - sock and ctx (write)") 513__failure 514//.errstr = "same insn cannot be used with different pointers", 515__msg("cannot write into sock") 516__naked void stx_sock_and_ctx_write(void) 517{ 518 asm volatile (" \ 519 r8 = r1; \ 520 /* struct bpf_sock *sock = bpf_sock_lookup(...); */\ 521" BPF_SK_LOOKUP(bpf_sk_lookup_tcp) 522" r2 = r0; \ 523 /* u64 foo; */ \ 524 /* void *target = &foo; */ \ 525 r6 = r10; \ 526 r6 += -8; \ 527 r1 = r8; \ 528 /* if (skb) *target = skb */ \ 529 if r1 == 0 goto l0_%=; \ 530 *(u64*)(r6 + 0) = r1; \ 531l0_%=: /* else *target = sock */ \ 532 if r1 != 0 goto l1_%=; \ 533 *(u64*)(r6 + 0) = r2; \ 534l1_%=: /* struct bpf_sock *sk = *target; */ \ 535 r1 = *(u64*)(r6 + 0); \ 536 /* if (sk) sk->mark = 42; bpf_sk_release(sk); */\ 537 if r1 == 0 goto l2_%=; \ 538 r3 = 42; \ 539 *(u32*)(r1 + %[bpf_sock_mark]) = r3; \ 540 call %[bpf_sk_release]; \ 541l2_%=: r0 = 0; \ 542 exit; \ 543" : 544 : __imm(bpf_sk_lookup_tcp), 545 __imm(bpf_sk_release), 546 __imm_const(bpf_sock_mark, offsetof(struct bpf_sock, mark)), 547 __imm_const(sizeof_bpf_sock_tuple, sizeof(struct bpf_sock_tuple)) 548 : __clobber_all); 549} 550 551SEC("socket") 552__description("unpriv: write pointer into map elem value") 553__success __failure_unpriv __msg_unpriv("R0 leaks addr") 554__retval(0) 555__naked void pointer_into_map_elem_value(void) 556{ 557 asm volatile (" \ 558 r1 = 0; \ 559 *(u64*)(r10 - 8) = r1; \ 560 r2 = r10; \ 561 r2 += -8; \ 562 r1 = %[map_hash_8b] ll; \ 563 call %[bpf_map_lookup_elem]; \ 564 if r0 == 0 goto l0_%=; \ 565 *(u64*)(r0 + 0) = r0; \ 566l0_%=: exit; \ 567" : 568 : __imm(bpf_map_lookup_elem), 569 __imm_addr(map_hash_8b) 570 : __clobber_all); 571} 572 573SEC("socket") 574__description("alu32: mov u32 const") 575__success __failure_unpriv __msg_unpriv("R7 invalid mem access 'scalar'") 576__retval(0) 577__naked void alu32_mov_u32_const(void) 578{ 579 asm volatile (" \ 580 w7 = 0; \ 581 w7 &= 1; \ 582 w0 = w7; \ 583 if r0 == 0 goto l0_%=; \ 584 r0 = *(u64*)(r7 + 0); \ 585l0_%=: exit; \ 586" ::: __clobber_all); 587} 588 589SEC("socket") 590__description("unpriv: partial copy of pointer") 591__success __failure_unpriv __msg_unpriv("R10 partial copy") 592__retval(0) 593__naked void unpriv_partial_copy_of_pointer(void) 594{ 595 asm volatile (" \ 596 w1 = w10; \ 597 r0 = 0; \ 598 exit; \ 599" ::: __clobber_all); 600} 601 602SEC("socket") 603__description("unpriv: pass pointer to tail_call") 604__success __failure_unpriv __msg_unpriv("R3 leaks addr into helper") 605__retval(0) 606__naked void pass_pointer_to_tail_call(void) 607{ 608 asm volatile (" \ 609 r3 = r1; \ 610 r2 = %[map_prog1_socket] ll; \ 611 call %[bpf_tail_call]; \ 612 r0 = 0; \ 613 exit; \ 614" : 615 : __imm(bpf_tail_call), 616 __imm_addr(map_prog1_socket) 617 : __clobber_all); 618} 619 620SEC("socket") 621__description("unpriv: cmp map pointer with zero") 622__success __failure_unpriv __msg_unpriv("R1 pointer comparison") 623__retval(0) 624__naked void cmp_map_pointer_with_zero(void) 625{ 626 asm volatile (" \ 627 r1 = 0; \ 628 r1 = %[map_hash_8b] ll; \ 629 if r1 == 0 goto l0_%=; \ 630l0_%=: r0 = 0; \ 631 exit; \ 632" : 633 : __imm_addr(map_hash_8b) 634 : __clobber_all); 635} 636 637SEC("socket") 638__description("unpriv: write into frame pointer") 639__failure __msg("frame pointer is read only") 640__failure_unpriv 641__naked void unpriv_write_into_frame_pointer(void) 642{ 643 asm volatile (" \ 644 r10 = r1; \ 645 r0 = 0; \ 646 exit; \ 647" ::: __clobber_all); 648} 649 650SEC("socket") 651__description("unpriv: spill/fill frame pointer") 652__failure __msg("frame pointer is read only") 653__failure_unpriv 654__naked void unpriv_spill_fill_frame_pointer(void) 655{ 656 asm volatile (" \ 657 r6 = r10; \ 658 r6 += -8; \ 659 *(u64*)(r6 + 0) = r10; \ 660 r10 = *(u64*)(r6 + 0); \ 661 r0 = 0; \ 662 exit; \ 663" ::: __clobber_all); 664} 665 666SEC("socket") 667__description("unpriv: cmp of frame pointer") 668__success __failure_unpriv __msg_unpriv("R10 pointer comparison") 669__retval(0) 670__naked void unpriv_cmp_of_frame_pointer(void) 671{ 672 asm volatile (" \ 673 if r10 == 0 goto l0_%=; \ 674l0_%=: r0 = 0; \ 675 exit; \ 676" ::: __clobber_all); 677} 678 679SEC("socket") 680__description("unpriv: adding of fp, reg") 681__success __failure_unpriv 682__msg_unpriv("R1 stack pointer arithmetic goes out of range") 683__retval(0) 684__naked void unpriv_adding_of_fp_reg(void) 685{ 686 asm volatile (" \ 687 r0 = 0; \ 688 r1 = 0; \ 689 r1 += r10; \ 690 *(u64*)(r1 - 8) = r0; \ 691 exit; \ 692" ::: __clobber_all); 693} 694 695SEC("socket") 696__description("unpriv: adding of fp, imm") 697__success __failure_unpriv 698__msg_unpriv("R1 stack pointer arithmetic goes out of range") 699__retval(0) 700__naked void unpriv_adding_of_fp_imm(void) 701{ 702 asm volatile (" \ 703 r0 = 0; \ 704 r1 = r10; \ 705 r1 += 0; \ 706 *(u64*)(r1 - 8) = r0; \ 707 exit; \ 708" ::: __clobber_all); 709} 710 711SEC("socket") 712__description("unpriv: cmp of stack pointer") 713__success __failure_unpriv __msg_unpriv("R2 pointer comparison") 714__retval(0) 715__naked void unpriv_cmp_of_stack_pointer(void) 716{ 717 asm volatile (" \ 718 r2 = r10; \ 719 r2 += -8; \ 720 if r2 == 0 goto l0_%=; \ 721l0_%=: r0 = 0; \ 722 exit; \ 723" ::: __clobber_all); 724} 725 726char _license[] SEC("license") = "GPL"; 727