1 // SPDX-License-Identifier: GPL-2.0 2 /* Converted from tools/testing/selftests/bpf/verifier/value_illegal_alu.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 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_HASH); 18 __uint(max_entries, 1); 19 __type(key, long long); 20 __type(value, struct test_val); 21 } map_hash_48b SEC(".maps"); 22 23 SEC("socket") 24 __description("map element value illegal alu op, 1") 25 __failure __msg("R0 bitwise operator &= on pointer") 26 __failure_unpriv 27 __naked void value_illegal_alu_op_1(void) 28 { 29 asm volatile (" \ 30 r2 = r10; \ 31 r2 += -8; \ 32 r1 = 0; \ 33 *(u64*)(r2 + 0) = r1; \ 34 r1 = %[map_hash_48b] ll; \ 35 call %[bpf_map_lookup_elem]; \ 36 if r0 == 0 goto l0_%=; \ 37 r0 &= 8; \ 38 r1 = 22; \ 39 *(u64*)(r0 + 0) = r1; \ 40 l0_%=: exit; \ 41 " : 42 : __imm(bpf_map_lookup_elem), 43 __imm_addr(map_hash_48b) 44 : __clobber_all); 45 } 46 47 SEC("socket") 48 __description("map element value illegal alu op, 2") 49 __failure __msg("R0 32-bit pointer arithmetic prohibited") 50 __failure_unpriv 51 __naked void value_illegal_alu_op_2(void) 52 { 53 asm volatile (" \ 54 r2 = r10; \ 55 r2 += -8; \ 56 r1 = 0; \ 57 *(u64*)(r2 + 0) = r1; \ 58 r1 = %[map_hash_48b] ll; \ 59 call %[bpf_map_lookup_elem]; \ 60 if r0 == 0 goto l0_%=; \ 61 w0 += 0; \ 62 r1 = 22; \ 63 *(u64*)(r0 + 0) = r1; \ 64 l0_%=: exit; \ 65 " : 66 : __imm(bpf_map_lookup_elem), 67 __imm_addr(map_hash_48b) 68 : __clobber_all); 69 } 70 71 SEC("socket") 72 __description("map element value illegal alu op, 3") 73 __failure __msg("R0 pointer arithmetic with /= operator") 74 __failure_unpriv 75 __naked void value_illegal_alu_op_3(void) 76 { 77 asm volatile (" \ 78 r2 = r10; \ 79 r2 += -8; \ 80 r1 = 0; \ 81 *(u64*)(r2 + 0) = r1; \ 82 r1 = %[map_hash_48b] ll; \ 83 call %[bpf_map_lookup_elem]; \ 84 if r0 == 0 goto l0_%=; \ 85 r0 /= 42; \ 86 r1 = 22; \ 87 *(u64*)(r0 + 0) = r1; \ 88 l0_%=: exit; \ 89 " : 90 : __imm(bpf_map_lookup_elem), 91 __imm_addr(map_hash_48b) 92 : __clobber_all); 93 } 94 95 SEC("socket") 96 __description("map element value illegal alu op, 4") 97 __failure __msg("invalid mem access 'scalar'") 98 __failure_unpriv __msg_unpriv("R0 pointer arithmetic prohibited") 99 __flag(BPF_F_ANY_ALIGNMENT) 100 __naked void value_illegal_alu_op_4(void) 101 { 102 asm volatile (" \ 103 r2 = r10; \ 104 r2 += -8; \ 105 r1 = 0; \ 106 *(u64*)(r2 + 0) = r1; \ 107 r1 = %[map_hash_48b] ll; \ 108 call %[bpf_map_lookup_elem]; \ 109 if r0 == 0 goto l0_%=; \ 110 r0 = be64 r0; \ 111 r1 = 22; \ 112 *(u64*)(r0 + 0) = r1; \ 113 l0_%=: exit; \ 114 " : 115 : __imm(bpf_map_lookup_elem), 116 __imm_addr(map_hash_48b) 117 : __clobber_all); 118 } 119 120 SEC("socket") 121 __description("map element value illegal alu op, 5") 122 __failure __msg("R0 invalid mem access 'scalar'") 123 __msg_unpriv("leaking pointer from stack off -8") 124 __flag(BPF_F_ANY_ALIGNMENT) 125 __naked void value_illegal_alu_op_5(void) 126 { 127 asm volatile (" \ 128 r2 = r10; \ 129 r2 += -8; \ 130 r1 = 0; \ 131 *(u64*)(r2 + 0) = r1; \ 132 r1 = %[map_hash_48b] ll; \ 133 call %[bpf_map_lookup_elem]; \ 134 if r0 == 0 goto l0_%=; \ 135 r3 = 4096; \ 136 r2 = r10; \ 137 r2 += -8; \ 138 *(u64*)(r2 + 0) = r0; \ 139 lock *(u64 *)(r2 + 0) += r3; \ 140 r0 = *(u64*)(r2 + 0); \ 141 r1 = 22; \ 142 *(u64*)(r0 + 0) = r1; \ 143 l0_%=: exit; \ 144 " : 145 : __imm(bpf_map_lookup_elem), 146 __imm_addr(map_hash_48b) 147 : __clobber_all); 148 } 149 150 SEC("socket") 151 __description("map_ptr illegal alu op, map_ptr = -map_ptr") 152 __failure __msg("R0 invalid mem access 'scalar'") 153 __failure_unpriv __msg_unpriv("R0 pointer arithmetic prohibited") 154 __flag(BPF_F_ANY_ALIGNMENT) 155 __naked void map_ptr_illegal_alu_op(void) 156 { 157 asm volatile (" \ 158 r0 = %[map_hash_48b] ll; \ 159 r0 = -r0; \ 160 r1 = 22; \ 161 *(u64*)(r0 + 0) = r1; \ 162 exit; \ 163 " : 164 : __imm_addr(map_hash_48b) 165 : __clobber_all); 166 } 167 168 SEC("flow_dissector") 169 __description("flow_keys illegal alu op with variable offset") 170 __failure __msg("R7 pointer arithmetic on flow_keys prohibited") 171 __naked void flow_keys_illegal_variable_offset_alu(void) 172 { 173 asm volatile(" \ 174 r6 = r1; \ 175 r7 = *(u64*)(r6 + %[flow_keys_off]); \ 176 r8 = 8; \ 177 r8 /= 1; \ 178 r8 &= 8; \ 179 r7 += r8; \ 180 r0 = *(u64*)(r7 + 0); \ 181 exit; \ 182 " : 183 : __imm_const(flow_keys_off, offsetof(struct __sk_buff, flow_keys)) 184 : __clobber_all); 185 } 186 187 #define DEFINE_BAD_OFFSET_TEST(name, op, off, imm) \ 188 SEC("socket") \ 189 __failure __msg("BPF_ALU uses reserved fields") \ 190 __naked void name(void) \ 191 { \ 192 asm volatile( \ 193 "r0 = 1;" \ 194 ".8byte %[insn];" \ 195 "r0 = 0;" \ 196 "exit;" \ 197 : \ 198 : __imm_insn(insn, BPF_RAW_INSN((op), 0, 0, (off), (imm))) \ 199 : __clobber_all); \ 200 } 201 202 /* 203 * Offset fields of 0 and 1 are legal for BPF_{DIV,MOD} instructions. 204 * Offset fields of 0 are legal for the rest of ALU instructions. 205 * Test that error is reported for illegal offsets, assuming that tests 206 * for legal offsets exist. 207 */ 208 DEFINE_BAD_OFFSET_TEST(bad_offset_divx, BPF_ALU64 | BPF_DIV | BPF_X, -1, 0) 209 DEFINE_BAD_OFFSET_TEST(bad_offset_modk, BPF_ALU64 | BPF_MOD | BPF_K, -1, 1) 210 DEFINE_BAD_OFFSET_TEST(bad_offset_addx, BPF_ALU64 | BPF_ADD | BPF_X, -1, 0) 211 DEFINE_BAD_OFFSET_TEST(bad_offset_divx2, BPF_ALU64 | BPF_DIV | BPF_X, 2, 0) 212 DEFINE_BAD_OFFSET_TEST(bad_offset_modk2, BPF_ALU64 | BPF_MOD | BPF_K, 2, 1) 213 DEFINE_BAD_OFFSET_TEST(bad_offset_addx2, BPF_ALU64 | BPF_ADD | BPF_X, 1, 0) 214 215 char _license[] SEC("license") = "GPL"; 216