xref: /linux/tools/testing/selftests/bpf/progs/verifier_movsx.c (revision 1f24458a1071f006e3f7449c08ae0f12af493923)
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("MOV32SX, S8")
14 __success __success_unpriv __retval(0x23)
15 __naked void mov32sx_s8(void)
16 {
17 	asm volatile ("					\
18 	w0 = 0xff23;					\
19 	w0 = (s8)w0;					\
20 	exit;						\
21 "	::: __clobber_all);
22 }
23 
24 SEC("socket")
25 __description("MOV32SX, S16")
26 __success __success_unpriv __retval(0xFFFFff23)
27 __naked void mov32sx_s16(void)
28 {
29 	asm volatile ("					\
30 	w0 = 0xff23;					\
31 	w0 = (s16)w0;					\
32 	exit;						\
33 "	::: __clobber_all);
34 }
35 
36 SEC("socket")
37 __description("MOV64SX, S8")
38 __success __success_unpriv __retval(-2)
39 __naked void mov64sx_s8(void)
40 {
41 	asm volatile ("					\
42 	r0 = 0x1fe;					\
43 	r0 = (s8)r0;					\
44 	exit;						\
45 "	::: __clobber_all);
46 }
47 
48 SEC("socket")
49 __description("MOV64SX, S16")
50 __success __success_unpriv __retval(0xf23)
51 __naked void mov64sx_s16(void)
52 {
53 	asm volatile ("					\
54 	r0 = 0xf0f23;					\
55 	r0 = (s16)r0;					\
56 	exit;						\
57 "	::: __clobber_all);
58 }
59 
60 SEC("socket")
61 __description("MOV64SX, S32")
62 __success __success_unpriv __retval(-1)
63 __naked void mov64sx_s32(void)
64 {
65 	asm volatile ("					\
66 	r0 = 0xfffffffe;				\
67 	r0 = (s32)r0;					\
68 	r0 >>= 1;					\
69 	exit;						\
70 "	::: __clobber_all);
71 }
72 
73 SEC("socket")
74 __description("MOV32SX, S8, range_check")
75 __success __success_unpriv __retval(1)
76 __naked void mov32sx_s8_range(void)
77 {
78 	asm volatile ("					\
79 	call %[bpf_get_prandom_u32];			\
80 	w1 = (s8)w0;					\
81 	/* w1 with s8 range */				\
82 	if w1 s> 0x7f goto l0_%=;			\
83 	if w1 s< -0x80 goto l0_%=;			\
84 	r0 = 1;						\
85 l1_%=:							\
86 	exit;						\
87 l0_%=:							\
88 	r0 = 2;						\
89 	goto l1_%=;					\
90 "	:
91 	: __imm(bpf_get_prandom_u32)
92 	: __clobber_all);
93 }
94 
95 SEC("socket")
96 __description("MOV32SX, S16, range_check")
97 __success __success_unpriv __retval(1)
98 __naked void mov32sx_s16_range(void)
99 {
100 	asm volatile ("					\
101 	call %[bpf_get_prandom_u32];			\
102 	w1 = (s16)w0;					\
103 	/* w1 with s16 range */				\
104 	if w1 s> 0x7fff goto l0_%=;			\
105 	if w1 s< -0x80ff goto l0_%=;			\
106 	r0 = 1;						\
107 l1_%=:							\
108 	exit;						\
109 l0_%=:							\
110 	r0 = 2;						\
111 	goto l1_%=;					\
112 "	:
113 	: __imm(bpf_get_prandom_u32)
114 	: __clobber_all);
115 }
116 
117 SEC("socket")
118 __description("MOV32SX, S16, range_check 2")
119 __success __success_unpriv __retval(1)
120 __naked void mov32sx_s16_range_2(void)
121 {
122 	asm volatile ("					\
123 	r1 = 65535;					\
124 	w2 = (s16)w1;					\
125 	r2 >>= 1;					\
126 	if r2 != 0x7fffFFFF goto l0_%=;			\
127 	r0 = 1;						\
128 l1_%=:							\
129 	exit;						\
130 l0_%=:							\
131 	r0 = 0;						\
132 	goto l1_%=;					\
133 "	:
134 	: __imm(bpf_get_prandom_u32)
135 	: __clobber_all);
136 }
137 
138 SEC("socket")
139 __description("MOV64SX, S8, range_check")
140 __success __success_unpriv __retval(1)
141 __naked void mov64sx_s8_range(void)
142 {
143 	asm volatile ("					\
144 	call %[bpf_get_prandom_u32];			\
145 	r1 = (s8)r0;					\
146 	/* r1 with s8 range */				\
147 	if r1 s> 0x7f goto l0_%=;			\
148 	if r1 s< -0x80 goto l0_%=;			\
149 	r0 = 1;						\
150 l1_%=:							\
151 	exit;						\
152 l0_%=:							\
153 	r0 = 2;						\
154 	goto l1_%=;					\
155 "	:
156 	: __imm(bpf_get_prandom_u32)
157 	: __clobber_all);
158 }
159 
160 SEC("socket")
161 __description("MOV64SX, S16, range_check")
162 __success __success_unpriv __retval(1)
163 __naked void mov64sx_s16_range(void)
164 {
165 	asm volatile ("					\
166 	call %[bpf_get_prandom_u32];			\
167 	r1 = (s16)r0;					\
168 	/* r1 with s16 range */				\
169 	if r1 s> 0x7fff goto l0_%=;			\
170 	if r1 s< -0x8000 goto l0_%=;			\
171 	r0 = 1;						\
172 l1_%=:							\
173 	exit;						\
174 l0_%=:							\
175 	r0 = 2;						\
176 	goto l1_%=;					\
177 "	:
178 	: __imm(bpf_get_prandom_u32)
179 	: __clobber_all);
180 }
181 
182 SEC("socket")
183 __description("MOV64SX, S32, range_check")
184 __success __success_unpriv __retval(1)
185 __naked void mov64sx_s32_range(void)
186 {
187 	asm volatile ("					\
188 	call %[bpf_get_prandom_u32];			\
189 	r1 = (s32)r0;					\
190 	/* r1 with s32 range */				\
191 	if r1 s> 0x7fffffff goto l0_%=;			\
192 	if r1 s< -0x80000000 goto l0_%=;		\
193 	r0 = 1;						\
194 l1_%=:							\
195 	exit;						\
196 l0_%=:							\
197 	r0 = 2;						\
198 	goto l1_%=;					\
199 "	:
200 	: __imm(bpf_get_prandom_u32)
201 	: __clobber_all);
202 }
203 
204 SEC("socket")
205 __description("MOV64SX, S16, R10 Sign Extension")
206 __failure __msg("R1 type=scalar expected=fp, pkt, pkt_meta, map_key, map_value, mem, ringbuf_mem, buf, trusted_ptr_")
207 __failure_unpriv __msg_unpriv("R10 sign-extension part of pointer")
208 __naked void mov64sx_s16_r10(void)
209 {
210 	asm volatile ("					\
211 	r1 = 553656332;					\
212 	*(u32 *)(r10 - 8) = r1; 			\
213 	r1 = (s16)r10;					\
214 	r1 += -8;					\
215 	r2 = 3;						\
216 	if r2 <= r1 goto l0_%=;				\
217 l0_%=:							\
218 	call %[bpf_trace_printk];			\
219 	r0 = 0;						\
220 	exit;						\
221 "	:
222 	: __imm(bpf_trace_printk)
223 	: __clobber_all);
224 }
225 
226 #else
227 
228 SEC("socket")
229 __description("cpuv4 is not supported by compiler or jit, use a dummy test")
230 __success
231 int dummy_test(void)
232 {
233 	return 0;
234 }
235 
236 #endif
237 
238 char _license[] SEC("license") = "GPL";
239