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