Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: verifier/leak_ptr.c converted to inline assembly

Test verifier/leak_ptr.c automatically converted to use inline assembly.

Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20230325025524.144043-27-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
583c7ce5 e2978755

+94 -67
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 23 23 #include "verifier_helper_value_access.skel.h" 24 24 #include "verifier_int_ptr.skel.h" 25 25 #include "verifier_ld_ind.skel.h" 26 + #include "verifier_leak_ptr.skel.h" 26 27 27 28 __maybe_unused 28 29 static void run_tests_aux(const char *skel_name, skel_elf_bytes_fn elf_bytes_factory) ··· 69 68 void test_verifier_helper_value_access(void) { RUN(verifier_helper_value_access); } 70 69 void test_verifier_int_ptr(void) { RUN(verifier_int_ptr); } 71 70 void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); } 71 + void test_verifier_leak_ptr(void) { RUN(verifier_leak_ptr); }
+92
tools/testing/selftests/bpf/progs/verifier_leak_ptr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Converted from tools/testing/selftests/bpf/verifier/leak_ptr.c */ 3 + 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 7 + 8 + struct { 9 + __uint(type, BPF_MAP_TYPE_HASH); 10 + __uint(max_entries, 1); 11 + __type(key, long long); 12 + __type(value, long long); 13 + } map_hash_8b SEC(".maps"); 14 + 15 + SEC("socket") 16 + __description("leak pointer into ctx 1") 17 + __failure __msg("BPF_ATOMIC stores into R1 ctx is not allowed") 18 + __failure_unpriv __msg_unpriv("R2 leaks addr into mem") 19 + __naked void leak_pointer_into_ctx_1(void) 20 + { 21 + asm volatile (" \ 22 + r0 = 0; \ 23 + *(u64*)(r1 + %[__sk_buff_cb_0]) = r0; \ 24 + r2 = %[map_hash_8b] ll; \ 25 + lock *(u64 *)(r1 + %[__sk_buff_cb_0]) += r2; \ 26 + exit; \ 27 + " : 28 + : __imm_addr(map_hash_8b), 29 + __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 30 + : __clobber_all); 31 + } 32 + 33 + SEC("socket") 34 + __description("leak pointer into ctx 2") 35 + __failure __msg("BPF_ATOMIC stores into R1 ctx is not allowed") 36 + __failure_unpriv __msg_unpriv("R10 leaks addr into mem") 37 + __naked void leak_pointer_into_ctx_2(void) 38 + { 39 + asm volatile (" \ 40 + r0 = 0; \ 41 + *(u64*)(r1 + %[__sk_buff_cb_0]) = r0; \ 42 + lock *(u64 *)(r1 + %[__sk_buff_cb_0]) += r10; \ 43 + exit; \ 44 + " : 45 + : __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 46 + : __clobber_all); 47 + } 48 + 49 + SEC("socket") 50 + __description("leak pointer into ctx 3") 51 + __success __failure_unpriv __msg_unpriv("R2 leaks addr into ctx") 52 + __retval(0) 53 + __naked void leak_pointer_into_ctx_3(void) 54 + { 55 + asm volatile (" \ 56 + r0 = 0; \ 57 + r2 = %[map_hash_8b] ll; \ 58 + *(u64*)(r1 + %[__sk_buff_cb_0]) = r2; \ 59 + exit; \ 60 + " : 61 + : __imm_addr(map_hash_8b), 62 + __imm_const(__sk_buff_cb_0, offsetof(struct __sk_buff, cb[0])) 63 + : __clobber_all); 64 + } 65 + 66 + SEC("socket") 67 + __description("leak pointer into map val") 68 + __success __failure_unpriv __msg_unpriv("R6 leaks addr into mem") 69 + __retval(0) 70 + __naked void leak_pointer_into_map_val(void) 71 + { 72 + asm volatile (" \ 73 + r6 = r1; \ 74 + r1 = 0; \ 75 + *(u64*)(r10 - 8) = r1; \ 76 + r2 = r10; \ 77 + r2 += -8; \ 78 + r1 = %[map_hash_8b] ll; \ 79 + call %[bpf_map_lookup_elem]; \ 80 + if r0 == 0 goto l0_%=; \ 81 + r3 = 0; \ 82 + *(u64*)(r0 + 0) = r3; \ 83 + lock *(u64 *)(r0 + 0) += r6; \ 84 + l0_%=: r0 = 0; \ 85 + exit; \ 86 + " : 87 + : __imm(bpf_map_lookup_elem), 88 + __imm_addr(map_hash_8b) 89 + : __clobber_all); 90 + } 91 + 92 + char _license[] SEC("license") = "GPL";
-67
tools/testing/selftests/bpf/verifier/leak_ptr.c
··· 1 - { 2 - "leak pointer into ctx 1", 3 - .insns = { 4 - BPF_MOV64_IMM(BPF_REG_0, 0), 5 - BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 6 - offsetof(struct __sk_buff, cb[0])), 7 - BPF_LD_MAP_FD(BPF_REG_2, 0), 8 - BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_1, BPF_REG_2, 9 - offsetof(struct __sk_buff, cb[0])), 10 - BPF_EXIT_INSN(), 11 - }, 12 - .fixup_map_hash_8b = { 2 }, 13 - .errstr_unpriv = "R2 leaks addr into mem", 14 - .result_unpriv = REJECT, 15 - .result = REJECT, 16 - .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", 17 - }, 18 - { 19 - "leak pointer into ctx 2", 20 - .insns = { 21 - BPF_MOV64_IMM(BPF_REG_0, 0), 22 - BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 23 - offsetof(struct __sk_buff, cb[0])), 24 - BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_1, BPF_REG_10, 25 - offsetof(struct __sk_buff, cb[0])), 26 - BPF_EXIT_INSN(), 27 - }, 28 - .errstr_unpriv = "R10 leaks addr into mem", 29 - .result_unpriv = REJECT, 30 - .result = REJECT, 31 - .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", 32 - }, 33 - { 34 - "leak pointer into ctx 3", 35 - .insns = { 36 - BPF_MOV64_IMM(BPF_REG_0, 0), 37 - BPF_LD_MAP_FD(BPF_REG_2, 0), 38 - BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, 39 - offsetof(struct __sk_buff, cb[0])), 40 - BPF_EXIT_INSN(), 41 - }, 42 - .fixup_map_hash_8b = { 1 }, 43 - .errstr_unpriv = "R2 leaks addr into ctx", 44 - .result_unpriv = REJECT, 45 - .result = ACCEPT, 46 - }, 47 - { 48 - "leak pointer into map val", 49 - .insns = { 50 - BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 51 - BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 52 - BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 53 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 54 - BPF_LD_MAP_FD(BPF_REG_1, 0), 55 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 56 - BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), 57 - BPF_MOV64_IMM(BPF_REG_3, 0), 58 - BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0), 59 - BPF_ATOMIC_OP(BPF_DW, BPF_ADD, BPF_REG_0, BPF_REG_6, 0), 60 - BPF_MOV64_IMM(BPF_REG_0, 0), 61 - BPF_EXIT_INSN(), 62 - }, 63 - .fixup_map_hash_8b = { 4 }, 64 - .errstr_unpriv = "R6 leaks addr into mem", 65 - .result_unpriv = REJECT, 66 - .result = ACCEPT, 67 - },