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 13SEC("socket") 14__description("LDSX, S8") 15__success __success_unpriv __retval(-2) 16__naked void ldsx_s8(void) 17{ 18 asm volatile ( 19 "r1 = 0x3fe;" 20 "*(u64 *)(r10 - 8) = r1;" 21#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 22 "r0 = *(s8 *)(r10 - 8);" 23#else 24 "r0 = *(s8 *)(r10 - 1);" 25#endif 26 "exit;" 27 ::: __clobber_all); 28} 29 30SEC("socket") 31__description("LDSX, S16") 32__success __success_unpriv __retval(-2) 33__naked void ldsx_s16(void) 34{ 35 asm volatile ( 36 "r1 = 0x3fffe;" 37 "*(u64 *)(r10 - 8) = r1;" 38#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 39 "r0 = *(s16 *)(r10 - 8);" 40#else 41 "r0 = *(s16 *)(r10 - 2);" 42#endif 43 "exit;" 44 ::: __clobber_all); 45} 46 47SEC("socket") 48__description("LDSX, S32") 49__success __success_unpriv __retval(-1) 50__naked void ldsx_s32(void) 51{ 52 asm volatile ( 53 "r1 = 0xfffffffe;" 54 "*(u64 *)(r10 - 8) = r1;" 55#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 56 "r0 = *(s32 *)(r10 - 8);" 57#else 58 "r0 = *(s32 *)(r10 - 4);" 59#endif 60 "r0 >>= 1;" 61 "exit;" 62 ::: __clobber_all); 63} 64 65SEC("socket") 66__description("LDSX, S8 range checking, privileged") 67__log_level(2) __success __retval(1) 68__msg("R1_w=scalar(smin=smin32=-128,smax=smax32=127)") 69__naked void ldsx_s8_range_priv(void) 70{ 71 asm volatile ( 72 "call %[bpf_get_prandom_u32];" 73 "*(u64 *)(r10 - 8) = r0;" 74#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 75 "r1 = *(s8 *)(r10 - 8);" 76#else 77 "r1 = *(s8 *)(r10 - 1);" 78#endif 79 /* r1 with s8 range */ 80 "if r1 s> 0x7f goto l0_%=;" 81 "if r1 s< -0x80 goto l0_%=;" 82 "r0 = 1;" 83"l1_%=:" 84 "exit;" 85"l0_%=:" 86 "r0 = 2;" 87 "goto l1_%=;" 88 : 89 : __imm(bpf_get_prandom_u32) 90 : __clobber_all); 91} 92 93SEC("socket") 94__description("LDSX, S16 range checking") 95__success __success_unpriv __retval(1) 96__naked void ldsx_s16_range(void) 97{ 98 asm volatile ( 99 "call %[bpf_get_prandom_u32];" 100 "*(u64 *)(r10 - 8) = r0;" 101#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 102 "r1 = *(s16 *)(r10 - 8);" 103#else 104 "r1 = *(s16 *)(r10 - 2);" 105#endif 106 /* r1 with s16 range */ 107 "if r1 s> 0x7fff goto l0_%=;" 108 "if r1 s< -0x8000 goto l0_%=;" 109 "r0 = 1;" 110"l1_%=:" 111 "exit;" 112"l0_%=:" 113 "r0 = 2;" 114 "goto l1_%=;" 115 : 116 : __imm(bpf_get_prandom_u32) 117 : __clobber_all); 118} 119 120SEC("socket") 121__description("LDSX, S32 range checking") 122__success __success_unpriv __retval(1) 123__naked void ldsx_s32_range(void) 124{ 125 asm volatile ( 126 "call %[bpf_get_prandom_u32];" 127 "*(u64 *)(r10 - 8) = r0;" 128#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 129 "r1 = *(s32 *)(r10 - 8);" 130#else 131 "r1 = *(s32 *)(r10 - 4);" 132#endif 133 /* r1 with s16 range */ 134 "if r1 s> 0x7fffFFFF goto l0_%=;" 135 "if r1 s< -0x80000000 goto l0_%=;" 136 "r0 = 1;" 137"l1_%=:" 138 "exit;" 139"l0_%=:" 140 "r0 = 2;" 141 "goto l1_%=;" 142 : 143 : __imm(bpf_get_prandom_u32) 144 : __clobber_all); 145} 146 147#else 148 149SEC("socket") 150__description("cpuv4 is not supported by compiler or jit, use a dummy test") 151__success 152int dummy_test(void) 153{ 154 return 0; 155} 156 157#endif 158 159char _license[] SEC("license") = "GPL"; 160