xref: /linux/tools/testing/selftests/bpf/progs/verifier_movsx.c (revision eb01fe7abbe2d0b38824d2a93fdb4cc3eaf2ccc1)
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 #else
228 
229 SEC("socket")
230 __description("cpuv4 is not supported by compiler or jit, use a dummy test")
231 __success
232 int dummy_test(void)
233 {
234 	return 0;
235 }
236 
237 #endif
238 
239 char _license[] SEC("license") = "GPL";
240