1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/bpf.h> 4 #include <bpf/bpf_helpers.h> 5 #include "bpf_misc.h" 6 7 #if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \ 8 (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \ 9 defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \ 10 defined(__TARGET_ARCH_loongarch)) && \ 11 __clang_major__ >= 18 12 13 SEC("socket") 14 __description("MOV32SX, S8") 15 __success __success_unpriv __retval(0x23) 16 __naked void mov32sx_s8(void) 17 { 18 asm volatile (" \ 19 w0 = 0xff23; \ 20 w0 = (s8)w0; \ 21 exit; \ 22 " ::: __clobber_all); 23 } 24 25 SEC("socket") 26 __description("MOV32SX, S16") 27 __success __success_unpriv __retval(0xFFFFff23) 28 __naked void mov32sx_s16(void) 29 { 30 asm volatile (" \ 31 w0 = 0xff23; \ 32 w0 = (s16)w0; \ 33 exit; \ 34 " ::: __clobber_all); 35 } 36 37 SEC("socket") 38 __description("MOV64SX, S8") 39 __success __success_unpriv __retval(-2) 40 __naked void mov64sx_s8(void) 41 { 42 asm volatile (" \ 43 r0 = 0x1fe; \ 44 r0 = (s8)r0; \ 45 exit; \ 46 " ::: __clobber_all); 47 } 48 49 SEC("socket") 50 __description("MOV64SX, S16") 51 __success __success_unpriv __retval(0xf23) 52 __naked void mov64sx_s16(void) 53 { 54 asm volatile (" \ 55 r0 = 0xf0f23; \ 56 r0 = (s16)r0; \ 57 exit; \ 58 " ::: __clobber_all); 59 } 60 61 SEC("socket") 62 __description("MOV64SX, S32") 63 __success __success_unpriv __retval(-1) 64 __naked void mov64sx_s32(void) 65 { 66 asm volatile (" \ 67 r0 = 0xfffffffe; \ 68 r0 = (s32)r0; \ 69 r0 >>= 1; \ 70 exit; \ 71 " ::: __clobber_all); 72 } 73 74 SEC("socket") 75 __description("MOV32SX, S8, range_check") 76 __success __success_unpriv __retval(1) 77 __naked void mov32sx_s8_range(void) 78 { 79 asm volatile (" \ 80 call %[bpf_get_prandom_u32]; \ 81 w1 = (s8)w0; \ 82 /* w1 with s8 range */ \ 83 if w1 s> 0x7f goto l0_%=; \ 84 if w1 s< -0x80 goto l0_%=; \ 85 r0 = 1; \ 86 l1_%=: \ 87 exit; \ 88 l0_%=: \ 89 r0 = 2; \ 90 goto l1_%=; \ 91 " : 92 : __imm(bpf_get_prandom_u32) 93 : __clobber_all); 94 } 95 96 SEC("socket") 97 __description("MOV32SX, S16, range_check") 98 __success __success_unpriv __retval(1) 99 __naked void mov32sx_s16_range(void) 100 { 101 asm volatile (" \ 102 call %[bpf_get_prandom_u32]; \ 103 w1 = (s16)w0; \ 104 /* w1 with s16 range */ \ 105 if w1 s> 0x7fff goto l0_%=; \ 106 if w1 s< -0x80ff goto l0_%=; \ 107 r0 = 1; \ 108 l1_%=: \ 109 exit; \ 110 l0_%=: \ 111 r0 = 2; \ 112 goto l1_%=; \ 113 " : 114 : __imm(bpf_get_prandom_u32) 115 : __clobber_all); 116 } 117 118 SEC("socket") 119 __description("MOV32SX, S16, range_check 2") 120 __success __success_unpriv __retval(1) 121 __naked void mov32sx_s16_range_2(void) 122 { 123 asm volatile (" \ 124 r1 = 65535; \ 125 w2 = (s16)w1; \ 126 r2 >>= 1; \ 127 if r2 != 0x7fffFFFF goto l0_%=; \ 128 r0 = 1; \ 129 l1_%=: \ 130 exit; \ 131 l0_%=: \ 132 r0 = 0; \ 133 goto l1_%=; \ 134 " : 135 : __imm(bpf_get_prandom_u32) 136 : __clobber_all); 137 } 138 139 SEC("socket") 140 __description("MOV64SX, S8, range_check") 141 __success __success_unpriv __retval(1) 142 __naked void mov64sx_s8_range(void) 143 { 144 asm volatile (" \ 145 call %[bpf_get_prandom_u32]; \ 146 r1 = (s8)r0; \ 147 /* r1 with s8 range */ \ 148 if r1 s> 0x7f goto l0_%=; \ 149 if r1 s< -0x80 goto l0_%=; \ 150 r0 = 1; \ 151 l1_%=: \ 152 exit; \ 153 l0_%=: \ 154 r0 = 2; \ 155 goto l1_%=; \ 156 " : 157 : __imm(bpf_get_prandom_u32) 158 : __clobber_all); 159 } 160 161 SEC("socket") 162 __description("MOV64SX, S16, range_check") 163 __success __success_unpriv __retval(1) 164 __naked void mov64sx_s16_range(void) 165 { 166 asm volatile (" \ 167 call %[bpf_get_prandom_u32]; \ 168 r1 = (s16)r0; \ 169 /* r1 with s16 range */ \ 170 if r1 s> 0x7fff goto l0_%=; \ 171 if r1 s< -0x8000 goto l0_%=; \ 172 r0 = 1; \ 173 l1_%=: \ 174 exit; \ 175 l0_%=: \ 176 r0 = 2; \ 177 goto l1_%=; \ 178 " : 179 : __imm(bpf_get_prandom_u32) 180 : __clobber_all); 181 } 182 183 SEC("socket") 184 __description("MOV64SX, S32, range_check") 185 __success __success_unpriv __retval(1) 186 __naked void mov64sx_s32_range(void) 187 { 188 asm volatile (" \ 189 call %[bpf_get_prandom_u32]; \ 190 r1 = (s32)r0; \ 191 /* r1 with s32 range */ \ 192 if r1 s> 0x7fffffff goto l0_%=; \ 193 if r1 s< -0x80000000 goto l0_%=; \ 194 r0 = 1; \ 195 l1_%=: \ 196 exit; \ 197 l0_%=: \ 198 r0 = 2; \ 199 goto l1_%=; \ 200 " : 201 : __imm(bpf_get_prandom_u32) 202 : __clobber_all); 203 } 204 205 SEC("socket") 206 __description("MOV64SX, S16, R10 Sign Extension") 207 __failure __msg("R1 type=scalar expected=fp, pkt, pkt_meta, map_key, map_value, mem, ringbuf_mem, buf, trusted_ptr_") 208 __failure_unpriv __msg_unpriv("R10 sign-extension part of pointer") 209 __naked void mov64sx_s16_r10(void) 210 { 211 asm volatile (" \ 212 r1 = 553656332; \ 213 *(u32 *)(r10 - 8) = r1; \ 214 r1 = (s16)r10; \ 215 r1 += -8; \ 216 r2 = 3; \ 217 if r2 <= r1 goto l0_%=; \ 218 l0_%=: \ 219 call %[bpf_trace_printk]; \ 220 r0 = 0; \ 221 exit; \ 222 " : 223 : __imm(bpf_trace_printk) 224 : __clobber_all); 225 } 226 227 SEC("socket") 228 __description("MOV32SX, S8, var_off u32_max") 229 __failure __msg("infinite loop detected") 230 __failure_unpriv __msg_unpriv("back-edge from insn 2 to 0") 231 __naked void mov64sx_s32_varoff_1(void) 232 { 233 asm volatile (" \ 234 l0_%=: \ 235 r3 = *(u8 *)(r10 -387); \ 236 w7 = (s8)w3; \ 237 if w7 >= 0x2533823b goto l0_%=; \ 238 w0 = 0; \ 239 exit; \ 240 " : 241 : 242 : __clobber_all); 243 } 244 245 SEC("socket") 246 __description("MOV32SX, S8, var_off not u32_max, positive after s8 extension") 247 __success __retval(0) 248 __failure_unpriv __msg_unpriv("frame pointer is read only") 249 __naked void mov64sx_s32_varoff_2(void) 250 { 251 asm volatile (" \ 252 call %[bpf_get_prandom_u32]; \ 253 r3 = r0; \ 254 r3 &= 0xf; \ 255 w7 = (s8)w3; \ 256 if w7 s>= 16 goto l0_%=; \ 257 w0 = 0; \ 258 exit; \ 259 l0_%=: \ 260 r10 = 1; \ 261 exit; \ 262 " : 263 : __imm(bpf_get_prandom_u32) 264 : __clobber_all); 265 } 266 267 SEC("socket") 268 __description("MOV32SX, S8, var_off not u32_max, negative after s8 extension") 269 __success __retval(0) 270 __failure_unpriv __msg_unpriv("frame pointer is read only") 271 __naked void mov64sx_s32_varoff_3(void) 272 { 273 asm volatile (" \ 274 call %[bpf_get_prandom_u32]; \ 275 r3 = r0; \ 276 r3 &= 0xf; \ 277 r3 |= 0x80; \ 278 w7 = (s8)w3; \ 279 if w7 s>= -5 goto l0_%=; \ 280 w0 = 0; \ 281 exit; \ 282 l0_%=: \ 283 r10 = 1; \ 284 exit; \ 285 " : 286 : __imm(bpf_get_prandom_u32) 287 : __clobber_all); 288 } 289 290 #else 291 292 SEC("socket") 293 __description("cpuv4 is not supported by compiler or jit, use a dummy test") 294 __success 295 int dummy_test(void) 296 { 297 return 0; 298 } 299 300 #endif 301 302 char _license[] SEC("license") = "GPL"; 303