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

selftests/bpf: verifier/ctx converted to inline assembly

Test verifier/ctx automatically converted to use inline assembly.

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

authored by

Eduard Zingerman and committed by
Alexei Starovoitov
fcd36964 37467c79

+223 -186
+2
tools/testing/selftests/bpf/prog_tests/verifier.c
··· 17 17 #include "verifier_cgroup_skb.skel.h" 18 18 #include "verifier_cgroup_storage.skel.h" 19 19 #include "verifier_const_or.skel.h" 20 + #include "verifier_ctx.skel.h" 20 21 #include "verifier_ctx_sk_msg.skel.h" 21 22 #include "verifier_direct_stack_access_wraparound.skel.h" 22 23 #include "verifier_div0.skel.h" ··· 97 96 void test_verifier_cgroup_skb(void) { RUN(verifier_cgroup_skb); } 98 97 void test_verifier_cgroup_storage(void) { RUN(verifier_cgroup_storage); } 99 98 void test_verifier_const_or(void) { RUN(verifier_const_or); } 99 + void test_verifier_ctx(void) { RUN(verifier_ctx); } 100 100 void test_verifier_ctx_sk_msg(void) { RUN(verifier_ctx_sk_msg); } 101 101 void test_verifier_direct_stack_access_wraparound(void) { RUN(verifier_direct_stack_access_wraparound); } 102 102 void test_verifier_div0(void) { RUN(verifier_div0); }
+221
tools/testing/selftests/bpf/progs/verifier_ctx.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Converted from tools/testing/selftests/bpf/verifier/ctx.c */ 3 + 4 + #include <linux/bpf.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_misc.h" 7 + 8 + SEC("tc") 9 + __description("context stores via BPF_ATOMIC") 10 + __failure __msg("BPF_ATOMIC stores into R1 ctx is not allowed") 11 + __naked void context_stores_via_bpf_atomic(void) 12 + { 13 + asm volatile (" \ 14 + r0 = 0; \ 15 + lock *(u32 *)(r1 + %[__sk_buff_mark]) += w0; \ 16 + exit; \ 17 + " : 18 + : __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 19 + : __clobber_all); 20 + } 21 + 22 + SEC("tc") 23 + __description("arithmetic ops make PTR_TO_CTX unusable") 24 + __failure __msg("dereference of modified ctx ptr") 25 + __naked void make_ptr_to_ctx_unusable(void) 26 + { 27 + asm volatile (" \ 28 + r1 += %[__imm_0]; \ 29 + r0 = *(u32*)(r1 + %[__sk_buff_mark]); \ 30 + exit; \ 31 + " : 32 + : __imm_const(__imm_0, 33 + offsetof(struct __sk_buff, data) - offsetof(struct __sk_buff, mark)), 34 + __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark)) 35 + : __clobber_all); 36 + } 37 + 38 + SEC("tc") 39 + __description("pass unmodified ctx pointer to helper") 40 + __success __retval(0) 41 + __naked void unmodified_ctx_pointer_to_helper(void) 42 + { 43 + asm volatile (" \ 44 + r2 = 0; \ 45 + call %[bpf_csum_update]; \ 46 + r0 = 0; \ 47 + exit; \ 48 + " : 49 + : __imm(bpf_csum_update) 50 + : __clobber_all); 51 + } 52 + 53 + SEC("tc") 54 + __description("pass modified ctx pointer to helper, 1") 55 + __failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 56 + __naked void ctx_pointer_to_helper_1(void) 57 + { 58 + asm volatile (" \ 59 + r1 += -612; \ 60 + r2 = 0; \ 61 + call %[bpf_csum_update]; \ 62 + r0 = 0; \ 63 + exit; \ 64 + " : 65 + : __imm(bpf_csum_update) 66 + : __clobber_all); 67 + } 68 + 69 + SEC("socket") 70 + __description("pass modified ctx pointer to helper, 2") 71 + __failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 72 + __failure_unpriv __msg_unpriv("negative offset ctx ptr R1 off=-612 disallowed") 73 + __naked void ctx_pointer_to_helper_2(void) 74 + { 75 + asm volatile (" \ 76 + r1 += -612; \ 77 + call %[bpf_get_socket_cookie]; \ 78 + r0 = 0; \ 79 + exit; \ 80 + " : 81 + : __imm(bpf_get_socket_cookie) 82 + : __clobber_all); 83 + } 84 + 85 + SEC("tc") 86 + __description("pass modified ctx pointer to helper, 3") 87 + __failure __msg("variable ctx access var_off=(0x0; 0x4)") 88 + __naked void ctx_pointer_to_helper_3(void) 89 + { 90 + asm volatile (" \ 91 + r3 = *(u32*)(r1 + 0); \ 92 + r3 &= 4; \ 93 + r1 += r3; \ 94 + r2 = 0; \ 95 + call %[bpf_csum_update]; \ 96 + r0 = 0; \ 97 + exit; \ 98 + " : 99 + : __imm(bpf_csum_update) 100 + : __clobber_all); 101 + } 102 + 103 + SEC("cgroup/sendmsg6") 104 + __description("pass ctx or null check, 1: ctx") 105 + __success 106 + __naked void or_null_check_1_ctx(void) 107 + { 108 + asm volatile (" \ 109 + call %[bpf_get_netns_cookie]; \ 110 + r0 = 0; \ 111 + exit; \ 112 + " : 113 + : __imm(bpf_get_netns_cookie) 114 + : __clobber_all); 115 + } 116 + 117 + SEC("cgroup/sendmsg6") 118 + __description("pass ctx or null check, 2: null") 119 + __success 120 + __naked void or_null_check_2_null(void) 121 + { 122 + asm volatile (" \ 123 + r1 = 0; \ 124 + call %[bpf_get_netns_cookie]; \ 125 + r0 = 0; \ 126 + exit; \ 127 + " : 128 + : __imm(bpf_get_netns_cookie) 129 + : __clobber_all); 130 + } 131 + 132 + SEC("cgroup/sendmsg6") 133 + __description("pass ctx or null check, 3: 1") 134 + __failure __msg("R1 type=scalar expected=ctx") 135 + __naked void or_null_check_3_1(void) 136 + { 137 + asm volatile (" \ 138 + r1 = 1; \ 139 + call %[bpf_get_netns_cookie]; \ 140 + r0 = 0; \ 141 + exit; \ 142 + " : 143 + : __imm(bpf_get_netns_cookie) 144 + : __clobber_all); 145 + } 146 + 147 + SEC("cgroup/sendmsg6") 148 + __description("pass ctx or null check, 4: ctx - const") 149 + __failure __msg("negative offset ctx ptr R1 off=-612 disallowed") 150 + __naked void null_check_4_ctx_const(void) 151 + { 152 + asm volatile (" \ 153 + r1 += -612; \ 154 + call %[bpf_get_netns_cookie]; \ 155 + r0 = 0; \ 156 + exit; \ 157 + " : 158 + : __imm(bpf_get_netns_cookie) 159 + : __clobber_all); 160 + } 161 + 162 + SEC("cgroup/connect4") 163 + __description("pass ctx or null check, 5: null (connect)") 164 + __success 165 + __naked void null_check_5_null_connect(void) 166 + { 167 + asm volatile (" \ 168 + r1 = 0; \ 169 + call %[bpf_get_netns_cookie]; \ 170 + r0 = 0; \ 171 + exit; \ 172 + " : 173 + : __imm(bpf_get_netns_cookie) 174 + : __clobber_all); 175 + } 176 + 177 + SEC("cgroup/post_bind4") 178 + __description("pass ctx or null check, 6: null (bind)") 179 + __success 180 + __naked void null_check_6_null_bind(void) 181 + { 182 + asm volatile (" \ 183 + r1 = 0; \ 184 + call %[bpf_get_netns_cookie]; \ 185 + r0 = 0; \ 186 + exit; \ 187 + " : 188 + : __imm(bpf_get_netns_cookie) 189 + : __clobber_all); 190 + } 191 + 192 + SEC("cgroup/post_bind4") 193 + __description("pass ctx or null check, 7: ctx (bind)") 194 + __success 195 + __naked void null_check_7_ctx_bind(void) 196 + { 197 + asm volatile (" \ 198 + call %[bpf_get_socket_cookie]; \ 199 + r0 = 0; \ 200 + exit; \ 201 + " : 202 + : __imm(bpf_get_socket_cookie) 203 + : __clobber_all); 204 + } 205 + 206 + SEC("cgroup/post_bind4") 207 + __description("pass ctx or null check, 8: null (bind)") 208 + __failure __msg("R1 type=scalar expected=ctx") 209 + __naked void null_check_8_null_bind(void) 210 + { 211 + asm volatile (" \ 212 + r1 = 0; \ 213 + call %[bpf_get_socket_cookie]; \ 214 + r0 = 0; \ 215 + exit; \ 216 + " : 217 + : __imm(bpf_get_socket_cookie) 218 + : __clobber_all); 219 + } 220 + 221 + char _license[] SEC("license") = "GPL";
-186
tools/testing/selftests/bpf/verifier/ctx.c
··· 1 - { 2 - "context stores via BPF_ATOMIC", 3 - .insns = { 4 - BPF_MOV64_IMM(BPF_REG_0, 0), 5 - BPF_ATOMIC_OP(BPF_W, BPF_ADD, BPF_REG_1, BPF_REG_0, offsetof(struct __sk_buff, mark)), 6 - BPF_EXIT_INSN(), 7 - }, 8 - .errstr = "BPF_ATOMIC stores into R1 ctx is not allowed", 9 - .result = REJECT, 10 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 11 - }, 12 - { 13 - "arithmetic ops make PTR_TO_CTX unusable", 14 - .insns = { 15 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 16 - offsetof(struct __sk_buff, data) - 17 - offsetof(struct __sk_buff, mark)), 18 - BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 19 - offsetof(struct __sk_buff, mark)), 20 - BPF_EXIT_INSN(), 21 - }, 22 - .errstr = "dereference of modified ctx ptr", 23 - .result = REJECT, 24 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 25 - }, 26 - { 27 - "pass unmodified ctx pointer to helper", 28 - .insns = { 29 - BPF_MOV64_IMM(BPF_REG_2, 0), 30 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 31 - BPF_FUNC_csum_update), 32 - BPF_MOV64_IMM(BPF_REG_0, 0), 33 - BPF_EXIT_INSN(), 34 - }, 35 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 36 - .result = ACCEPT, 37 - }, 38 - { 39 - "pass modified ctx pointer to helper, 1", 40 - .insns = { 41 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612), 42 - BPF_MOV64_IMM(BPF_REG_2, 0), 43 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 44 - BPF_FUNC_csum_update), 45 - BPF_MOV64_IMM(BPF_REG_0, 0), 46 - BPF_EXIT_INSN(), 47 - }, 48 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 49 - .result = REJECT, 50 - .errstr = "negative offset ctx ptr R1 off=-612 disallowed", 51 - }, 52 - { 53 - "pass modified ctx pointer to helper, 2", 54 - .insns = { 55 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612), 56 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 57 - BPF_FUNC_get_socket_cookie), 58 - BPF_MOV64_IMM(BPF_REG_0, 0), 59 - BPF_EXIT_INSN(), 60 - }, 61 - .result_unpriv = REJECT, 62 - .result = REJECT, 63 - .errstr_unpriv = "negative offset ctx ptr R1 off=-612 disallowed", 64 - .errstr = "negative offset ctx ptr R1 off=-612 disallowed", 65 - }, 66 - { 67 - "pass modified ctx pointer to helper, 3", 68 - .insns = { 69 - BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 0), 70 - BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 4), 71 - BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3), 72 - BPF_MOV64_IMM(BPF_REG_2, 0), 73 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 74 - BPF_FUNC_csum_update), 75 - BPF_MOV64_IMM(BPF_REG_0, 0), 76 - BPF_EXIT_INSN(), 77 - }, 78 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 79 - .result = REJECT, 80 - .errstr = "variable ctx access var_off=(0x0; 0x4)", 81 - }, 82 - { 83 - "pass ctx or null check, 1: ctx", 84 - .insns = { 85 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 86 - BPF_FUNC_get_netns_cookie), 87 - BPF_MOV64_IMM(BPF_REG_0, 0), 88 - BPF_EXIT_INSN(), 89 - }, 90 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 91 - .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 92 - .result = ACCEPT, 93 - }, 94 - { 95 - "pass ctx or null check, 2: null", 96 - .insns = { 97 - BPF_MOV64_IMM(BPF_REG_1, 0), 98 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 99 - BPF_FUNC_get_netns_cookie), 100 - BPF_MOV64_IMM(BPF_REG_0, 0), 101 - BPF_EXIT_INSN(), 102 - }, 103 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 104 - .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 105 - .result = ACCEPT, 106 - }, 107 - { 108 - "pass ctx or null check, 3: 1", 109 - .insns = { 110 - BPF_MOV64_IMM(BPF_REG_1, 1), 111 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 112 - BPF_FUNC_get_netns_cookie), 113 - BPF_MOV64_IMM(BPF_REG_0, 0), 114 - BPF_EXIT_INSN(), 115 - }, 116 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 117 - .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 118 - .result = REJECT, 119 - .errstr = "R1 type=scalar expected=ctx", 120 - }, 121 - { 122 - "pass ctx or null check, 4: ctx - const", 123 - .insns = { 124 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612), 125 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 126 - BPF_FUNC_get_netns_cookie), 127 - BPF_MOV64_IMM(BPF_REG_0, 0), 128 - BPF_EXIT_INSN(), 129 - }, 130 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 131 - .expected_attach_type = BPF_CGROUP_UDP6_SENDMSG, 132 - .result = REJECT, 133 - .errstr = "negative offset ctx ptr R1 off=-612 disallowed", 134 - }, 135 - { 136 - "pass ctx or null check, 5: null (connect)", 137 - .insns = { 138 - BPF_MOV64_IMM(BPF_REG_1, 0), 139 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 140 - BPF_FUNC_get_netns_cookie), 141 - BPF_MOV64_IMM(BPF_REG_0, 0), 142 - BPF_EXIT_INSN(), 143 - }, 144 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR, 145 - .expected_attach_type = BPF_CGROUP_INET4_CONNECT, 146 - .result = ACCEPT, 147 - }, 148 - { 149 - "pass ctx or null check, 6: null (bind)", 150 - .insns = { 151 - BPF_MOV64_IMM(BPF_REG_1, 0), 152 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 153 - BPF_FUNC_get_netns_cookie), 154 - BPF_MOV64_IMM(BPF_REG_0, 0), 155 - BPF_EXIT_INSN(), 156 - }, 157 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 158 - .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 159 - .result = ACCEPT, 160 - }, 161 - { 162 - "pass ctx or null check, 7: ctx (bind)", 163 - .insns = { 164 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 165 - BPF_FUNC_get_socket_cookie), 166 - BPF_MOV64_IMM(BPF_REG_0, 0), 167 - BPF_EXIT_INSN(), 168 - }, 169 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 170 - .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 171 - .result = ACCEPT, 172 - }, 173 - { 174 - "pass ctx or null check, 8: null (bind)", 175 - .insns = { 176 - BPF_MOV64_IMM(BPF_REG_1, 0), 177 - BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 178 - BPF_FUNC_get_socket_cookie), 179 - BPF_MOV64_IMM(BPF_REG_0, 0), 180 - BPF_EXIT_INSN(), 181 - }, 182 - .prog_type = BPF_PROG_TYPE_CGROUP_SOCK, 183 - .expected_attach_type = BPF_CGROUP_INET4_POST_BIND, 184 - .result = REJECT, 185 - .errstr = "R1 type=scalar expected=ctx", 186 - },