1// SPDX-License-Identifier: GPL-2.0
2/* Converted from tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c */
3
4#include <linux/bpf.h>
5#include <bpf/bpf_helpers.h>
6#include "bpf_misc.h"
7
8struct {
9	__uint(type, BPF_MAP_TYPE_HASH);
10	__uint(max_entries, 1);
11	__type(key, long long);
12	__type(value, long long);
13} map_hash_8b SEC(".maps");
14
15SEC("socket")
16__description("bounds checks mixing signed and unsigned, positive bounds")
17__failure __msg("unbounded min value")
18__failure_unpriv
19__naked void signed_and_unsigned_positive_bounds(void)
20{
21	asm volatile ("					\
22	call %[bpf_ktime_get_ns];			\
23	*(u64*)(r10 - 16) = r0;				\
24	r1 = 0;						\
25	*(u64*)(r10 - 8) = r1;				\
26	r2 = r10;					\
27	r2 += -8;					\
28	r1 = %[map_hash_8b] ll;				\
29	call %[bpf_map_lookup_elem];			\
30	if r0 == 0 goto l0_%=;				\
31	r1 = *(u64*)(r10 - 16);				\
32	r2 = 2;						\
33	if r2 >= r1 goto l0_%=;				\
34	if r1 s> 4 goto l0_%=;				\
35	r0 += r1;					\
36	r1 = 0;						\
37	*(u8*)(r0 + 0) = r1;				\
38l0_%=:	r0 = 0;						\
39	exit;						\
40"	:
41	: __imm(bpf_ktime_get_ns),
42	  __imm(bpf_map_lookup_elem),
43	  __imm_addr(map_hash_8b)
44	: __clobber_all);
45}
46
47SEC("socket")
48__description("bounds checks mixing signed and unsigned")
49__failure __msg("unbounded min value")
50__failure_unpriv
51__naked void checks_mixing_signed_and_unsigned(void)
52{
53	asm volatile ("					\
54	call %[bpf_ktime_get_ns];			\
55	*(u64*)(r10 - 16) = r0;				\
56	r1 = 0;						\
57	*(u64*)(r10 - 8) = r1;				\
58	r2 = r10;					\
59	r2 += -8;					\
60	r1 = %[map_hash_8b] ll;				\
61	call %[bpf_map_lookup_elem];			\
62	if r0 == 0 goto l0_%=;				\
63	r1 = *(u64*)(r10 - 16);				\
64	r2 = -1;					\
65	if r1 > r2 goto l0_%=;				\
66	if r1 s> 1 goto l0_%=;				\
67	r0 += r1;					\
68	r1 = 0;						\
69	*(u8*)(r0 + 0) = r1;				\
70l0_%=:	r0 = 0;						\
71	exit;						\
72"	:
73	: __imm(bpf_ktime_get_ns),
74	  __imm(bpf_map_lookup_elem),
75	  __imm_addr(map_hash_8b)
76	: __clobber_all);
77}
78
79SEC("socket")
80__description("bounds checks mixing signed and unsigned, variant 2")
81__failure __msg("unbounded min value")
82__failure_unpriv
83__naked void signed_and_unsigned_variant_2(void)
84{
85	asm volatile ("					\
86	call %[bpf_ktime_get_ns];			\
87	*(u64*)(r10 - 16) = r0;				\
88	r1 = 0;						\
89	*(u64*)(r10 - 8) = r1;				\
90	r2 = r10;					\
91	r2 += -8;					\
92	r1 = %[map_hash_8b] ll;				\
93	call %[bpf_map_lookup_elem];			\
94	if r0 == 0 goto l0_%=;				\
95	r1 = *(u64*)(r10 - 16);				\
96	r2 = -1;					\
97	if r1 > r2 goto l0_%=;				\
98	r8 = 0;						\
99	r8 += r1;					\
100	if r8 s> 1 goto l0_%=;				\
101	r0 += r8;					\
102	r0 = 0;						\
103	*(u8*)(r8 + 0) = r0;				\
104l0_%=:	r0 = 0;						\
105	exit;						\
106"	:
107	: __imm(bpf_ktime_get_ns),
108	  __imm(bpf_map_lookup_elem),
109	  __imm_addr(map_hash_8b)
110	: __clobber_all);
111}
112
113SEC("socket")
114__description("bounds checks mixing signed and unsigned, variant 3")
115__failure __msg("unbounded min value")
116__failure_unpriv
117__naked void signed_and_unsigned_variant_3(void)
118{
119	asm volatile ("					\
120	call %[bpf_ktime_get_ns];			\
121	*(u64*)(r10 - 16) = r0;				\
122	r1 = 0;						\
123	*(u64*)(r10 - 8) = r1;				\
124	r2 = r10;					\
125	r2 += -8;					\
126	r1 = %[map_hash_8b] ll;				\
127	call %[bpf_map_lookup_elem];			\
128	if r0 == 0 goto l0_%=;				\
129	r1 = *(u64*)(r10 - 16);				\
130	r2 = -1;					\
131	if r1 > r2 goto l0_%=;				\
132	r8 = r1;					\
133	if r8 s> 1 goto l0_%=;				\
134	r0 += r8;					\
135	r0 = 0;						\
136	*(u8*)(r8 + 0) = r0;				\
137l0_%=:	r0 = 0;						\
138	exit;						\
139"	:
140	: __imm(bpf_ktime_get_ns),
141	  __imm(bpf_map_lookup_elem),
142	  __imm_addr(map_hash_8b)
143	: __clobber_all);
144}
145
146SEC("socket")
147__description("bounds checks mixing signed and unsigned, variant 4")
148__success __success_unpriv __retval(0)
149__naked void signed_and_unsigned_variant_4(void)
150{
151	asm volatile ("					\
152	call %[bpf_ktime_get_ns];			\
153	*(u64*)(r10 - 16) = r0;				\
154	r1 = 0;						\
155	*(u64*)(r10 - 8) = r1;				\
156	r2 = r10;					\
157	r2 += -8;					\
158	r1 = %[map_hash_8b] ll;				\
159	call %[bpf_map_lookup_elem];			\
160	if r0 == 0 goto l0_%=;				\
161	r1 = *(u64*)(r10 - 16);				\
162	r2 = 1;						\
163	r1 &= r2;					\
164	if r1 s> 1 goto l0_%=;				\
165	r0 += r1;					\
166	r1 = 0;						\
167	*(u8*)(r0 + 0) = r1;				\
168l0_%=:	r0 = 0;						\
169	exit;						\
170"	:
171	: __imm(bpf_ktime_get_ns),
172	  __imm(bpf_map_lookup_elem),
173	  __imm_addr(map_hash_8b)
174	: __clobber_all);
175}
176
177SEC("socket")
178__description("bounds checks mixing signed and unsigned, variant 5")
179__failure __msg("unbounded min value")
180__failure_unpriv
181__naked void signed_and_unsigned_variant_5(void)
182{
183	asm volatile ("					\
184	call %[bpf_ktime_get_ns];			\
185	*(u64*)(r10 - 16) = r0;				\
186	r1 = 0;						\
187	*(u64*)(r10 - 8) = r1;				\
188	r2 = r10;					\
189	r2 += -8;					\
190	r1 = %[map_hash_8b] ll;				\
191	call %[bpf_map_lookup_elem];			\
192	if r0 == 0 goto l0_%=;				\
193	r1 = *(u64*)(r10 - 16);				\
194	r2 = -1;					\
195	if r1 > r2 goto l0_%=;				\
196	if r1 s> 1 goto l0_%=;				\
197	r0 += 4;					\
198	r0 -= r1;					\
199	r1 = 0;						\
200	*(u8*)(r0 + 0) = r1;				\
201	r0 = 0;						\
202l0_%=:	exit;						\
203"	:
204	: __imm(bpf_ktime_get_ns),
205	  __imm(bpf_map_lookup_elem),
206	  __imm_addr(map_hash_8b)
207	: __clobber_all);
208}
209
210SEC("socket")
211__description("bounds checks mixing signed and unsigned, variant 6")
212__failure __msg("R4 min value is negative, either use unsigned")
213__failure_unpriv
214__naked void signed_and_unsigned_variant_6(void)
215{
216	asm volatile ("					\
217	r9 = r1;					\
218	call %[bpf_ktime_get_ns];			\
219	*(u64*)(r10 - 16) = r0;				\
220	r1 = r9;					\
221	r2 = 0;						\
222	r3 = r10;					\
223	r3 += -512;					\
224	r4 = *(u64*)(r10 - 16);				\
225	r6 = -1;					\
226	if r4 > r6 goto l0_%=;				\
227	if r4 s> 1 goto l0_%=;				\
228	r4 += 1;					\
229	r5 = 0;						\
230	r6 = 0;						\
231	*(u16*)(r10 - 512) = r6;			\
232	call %[bpf_skb_load_bytes];			\
233l0_%=:	r0 = 0;						\
234	exit;						\
235"	:
236	: __imm(bpf_ktime_get_ns),
237	  __imm(bpf_skb_load_bytes)
238	: __clobber_all);
239}
240
241SEC("socket")
242__description("bounds checks mixing signed and unsigned, variant 7")
243__success __success_unpriv __retval(0)
244__naked void signed_and_unsigned_variant_7(void)
245{
246	asm volatile ("					\
247	call %[bpf_ktime_get_ns];			\
248	*(u64*)(r10 - 16) = r0;				\
249	r1 = 0;						\
250	*(u64*)(r10 - 8) = r1;				\
251	r2 = r10;					\
252	r2 += -8;					\
253	r1 = %[map_hash_8b] ll;				\
254	call %[bpf_map_lookup_elem];			\
255	if r0 == 0 goto l0_%=;				\
256	r1 = *(u64*)(r10 - 16);				\
257	r2 = %[__imm_0];				\
258	if r1 > r2 goto l0_%=;				\
259	if r1 s> 1 goto l0_%=;				\
260	r0 += r1;					\
261	r1 = 0;						\
262	*(u8*)(r0 + 0) = r1;				\
263l0_%=:	r0 = 0;						\
264	exit;						\
265"	:
266	: __imm(bpf_ktime_get_ns),
267	  __imm(bpf_map_lookup_elem),
268	  __imm_addr(map_hash_8b),
269	  __imm_const(__imm_0, 1024 * 1024 * 1024)
270	: __clobber_all);
271}
272
273SEC("socket")
274__description("bounds checks mixing signed and unsigned, variant 8")
275__failure __msg("unbounded min value")
276__failure_unpriv
277__naked void signed_and_unsigned_variant_8(void)
278{
279	asm volatile ("					\
280	call %[bpf_ktime_get_ns];			\
281	*(u64*)(r10 - 16) = r0;				\
282	r1 = 0;						\
283	*(u64*)(r10 - 8) = r1;				\
284	r2 = r10;					\
285	r2 += -8;					\
286	r1 = %[map_hash_8b] ll;				\
287	call %[bpf_map_lookup_elem];			\
288	if r0 == 0 goto l0_%=;				\
289	r1 = *(u64*)(r10 - 16);				\
290	r2 = -1;					\
291	if r2 > r1 goto l1_%=;				\
292	r0 = 0;						\
293	exit;						\
294l1_%=:	if r1 s> 1 goto l0_%=;				\
295	r0 += r1;					\
296	r1 = 0;						\
297	*(u8*)(r0 + 0) = r1;				\
298l0_%=:	r0 = 0;						\
299	exit;						\
300"	:
301	: __imm(bpf_ktime_get_ns),
302	  __imm(bpf_map_lookup_elem),
303	  __imm_addr(map_hash_8b)
304	: __clobber_all);
305}
306
307SEC("socket")
308__description("bounds checks mixing signed and unsigned, variant 9")
309__success __success_unpriv __retval(0)
310__naked void signed_and_unsigned_variant_9(void)
311{
312	asm volatile ("					\
313	call %[bpf_ktime_get_ns];			\
314	*(u64*)(r10 - 16) = r0;				\
315	r1 = 0;						\
316	*(u64*)(r10 - 8) = r1;				\
317	r2 = r10;					\
318	r2 += -8;					\
319	r1 = %[map_hash_8b] ll;				\
320	call %[bpf_map_lookup_elem];			\
321	if r0 == 0 goto l0_%=;				\
322	r1 = *(u64*)(r10 - 16);				\
323	r2 = -9223372036854775808ULL ll;		\
324	if r2 > r1 goto l1_%=;				\
325	r0 = 0;						\
326	exit;						\
327l1_%=:	if r1 s> 1 goto l0_%=;				\
328	r0 += r1;					\
329	r1 = 0;						\
330	*(u8*)(r0 + 0) = r1;				\
331l0_%=:	r0 = 0;						\
332	exit;						\
333"	:
334	: __imm(bpf_ktime_get_ns),
335	  __imm(bpf_map_lookup_elem),
336	  __imm_addr(map_hash_8b)
337	: __clobber_all);
338}
339
340SEC("socket")
341__description("bounds checks mixing signed and unsigned, variant 10")
342__failure __msg("unbounded min value")
343__failure_unpriv
344__naked void signed_and_unsigned_variant_10(void)
345{
346	asm volatile ("					\
347	call %[bpf_ktime_get_ns];			\
348	*(u64*)(r10 - 16) = r0;				\
349	r1 = 0;						\
350	*(u64*)(r10 - 8) = r1;				\
351	r2 = r10;					\
352	r2 += -8;					\
353	r1 = %[map_hash_8b] ll;				\
354	call %[bpf_map_lookup_elem];			\
355	if r0 == 0 goto l0_%=;				\
356	r1 = *(u64*)(r10 - 16);				\
357	r2 = -1;						\
358	if r2 > r1 goto l1_%=;				\
359	r0 = 0;						\
360	exit;						\
361l1_%=:	if r1 s> 1 goto l0_%=;				\
362	r0 += r1;					\
363	r1 = 0;						\
364	*(u8*)(r0 + 0) = r1;				\
365l0_%=:	r0 = 0;						\
366	exit;						\
367"	:
368	: __imm(bpf_ktime_get_ns),
369	  __imm(bpf_map_lookup_elem),
370	  __imm_addr(map_hash_8b)
371	: __clobber_all);
372}
373
374SEC("socket")
375__description("bounds checks mixing signed and unsigned, variant 11")
376__failure __msg("unbounded min value")
377__failure_unpriv
378__naked void signed_and_unsigned_variant_11(void)
379{
380	asm volatile ("					\
381	call %[bpf_ktime_get_ns];			\
382	*(u64*)(r10 - 16) = r0;				\
383	r1 = 0;						\
384	*(u64*)(r10 - 8) = r1;				\
385	r2 = r10;					\
386	r2 += -8;					\
387	r1 = %[map_hash_8b] ll;				\
388	call %[bpf_map_lookup_elem];			\
389	if r0 == 0 goto l0_%=;				\
390	r1 = *(u64*)(r10 - 16);				\
391	r2 = -1;					\
392	if r2 >= r1 goto l1_%=;				\
393	/* Dead branch. */				\
394	r0 = 0;						\
395	exit;						\
396l1_%=:	if r1 s> 1 goto l0_%=;				\
397	r0 += r1;					\
398	r1 = 0;						\
399	*(u8*)(r0 + 0) = r1;				\
400l0_%=:	r0 = 0;						\
401	exit;						\
402"	:
403	: __imm(bpf_ktime_get_ns),
404	  __imm(bpf_map_lookup_elem),
405	  __imm_addr(map_hash_8b)
406	: __clobber_all);
407}
408
409SEC("socket")
410__description("bounds checks mixing signed and unsigned, variant 12")
411__failure __msg("unbounded min value")
412__failure_unpriv
413__naked void signed_and_unsigned_variant_12(void)
414{
415	asm volatile ("					\
416	call %[bpf_ktime_get_ns];			\
417	*(u64*)(r10 - 16) = r0;				\
418	r1 = 0;						\
419	*(u64*)(r10 - 8) = r1;				\
420	r2 = r10;					\
421	r2 += -8;					\
422	r1 = %[map_hash_8b] ll;				\
423	call %[bpf_map_lookup_elem];			\
424	if r0 == 0 goto l0_%=;				\
425	r1 = *(u64*)(r10 - 16);				\
426	r2 = -6;					\
427	if r2 >= r1 goto l1_%=;				\
428	r0 = 0;						\
429	exit;						\
430l1_%=:	if r1 s> 1 goto l0_%=;				\
431	r0 += r1;					\
432	r1 = 0;						\
433	*(u8*)(r0 + 0) = r1;				\
434l0_%=:	r0 = 0;						\
435	exit;						\
436"	:
437	: __imm(bpf_ktime_get_ns),
438	  __imm(bpf_map_lookup_elem),
439	  __imm_addr(map_hash_8b)
440	: __clobber_all);
441}
442
443SEC("socket")
444__description("bounds checks mixing signed and unsigned, variant 13")
445__failure __msg("unbounded min value")
446__failure_unpriv
447__naked void signed_and_unsigned_variant_13(void)
448{
449	asm volatile ("					\
450	call %[bpf_ktime_get_ns];			\
451	*(u64*)(r10 - 16) = r0;				\
452	r1 = 0;						\
453	*(u64*)(r10 - 8) = r1;				\
454	r2 = r10;					\
455	r2 += -8;					\
456	r1 = %[map_hash_8b] ll;				\
457	call %[bpf_map_lookup_elem];			\
458	if r0 == 0 goto l0_%=;				\
459	r1 = *(u64*)(r10 - 16);				\
460	r2 = 2;						\
461	if r2 >= r1 goto l0_%=;				\
462	r7 = 1;						\
463	if r7 s> 0 goto l1_%=;				\
464l0_%=:	r0 = 0;						\
465	exit;						\
466l1_%=:	r7 += r1;					\
467	if r7 s> 4 goto l2_%=;				\
468	r0 += r7;					\
469	r1 = 0;						\
470	*(u8*)(r0 + 0) = r1;				\
471l2_%=:	r0 = 0;						\
472	exit;						\
473"	:
474	: __imm(bpf_ktime_get_ns),
475	  __imm(bpf_map_lookup_elem),
476	  __imm_addr(map_hash_8b)
477	: __clobber_all);
478}
479
480SEC("socket")
481__description("bounds checks mixing signed and unsigned, variant 14")
482__failure __msg("unbounded min value")
483__failure_unpriv
484__naked void signed_and_unsigned_variant_14(void)
485{
486	asm volatile ("					\
487	r9 = *(u32*)(r1 + %[__sk_buff_mark]);		\
488	call %[bpf_ktime_get_ns];			\
489	*(u64*)(r10 - 16) = r0;				\
490	r1 = 0;						\
491	*(u64*)(r10 - 8) = r1;				\
492	r2 = r10;					\
493	r2 += -8;					\
494	r1 = %[map_hash_8b] ll;				\
495	call %[bpf_map_lookup_elem];			\
496	if r0 == 0 goto l0_%=;				\
497	r1 = *(u64*)(r10 - 16);				\
498	r2 = -1;					\
499	r8 = 2;						\
500	if r9 == 42 goto l1_%=;				\
501	if r8 s> r1 goto l2_%=;				\
502l3_%=:	if r1 s> 1 goto l2_%=;				\
503	r0 += r1;					\
504l0_%=:	r1 = 0;						\
505	*(u8*)(r0 + 0) = r1;				\
506l2_%=:	r0 = 0;						\
507	exit;						\
508l1_%=:	if r1 > r2 goto l2_%=;				\
509	goto l3_%=;					\
510"	:
511	: __imm(bpf_ktime_get_ns),
512	  __imm(bpf_map_lookup_elem),
513	  __imm_addr(map_hash_8b),
514	  __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
515	: __clobber_all);
516}
517
518SEC("socket")
519__description("bounds checks mixing signed and unsigned, variant 15")
520__failure __msg("unbounded min value")
521__failure_unpriv
522__naked void signed_and_unsigned_variant_15(void)
523{
524	asm volatile ("					\
525	call %[bpf_ktime_get_ns];			\
526	*(u64*)(r10 - 16) = r0;				\
527	r1 = 0;						\
528	*(u64*)(r10 - 8) = r1;				\
529	r2 = r10;					\
530	r2 += -8;					\
531	r1 = %[map_hash_8b] ll;				\
532	call %[bpf_map_lookup_elem];			\
533	if r0 == 0 goto l0_%=;				\
534	r1 = *(u64*)(r10 - 16);				\
535	r2 = -6;					\
536	if r2 >= r1 goto l1_%=;				\
537l0_%=:	r0 = 0;						\
538	exit;						\
539l1_%=:	r0 += r1;					\
540	if r0 > 1 goto l2_%=;				\
541	r0 = 0;						\
542	exit;						\
543l2_%=:	r1 = 0;						\
544	*(u8*)(r0 + 0) = r1;				\
545	r0 = 0;						\
546	exit;						\
547"	:
548	: __imm(bpf_ktime_get_ns),
549	  __imm(bpf_map_lookup_elem),
550	  __imm_addr(map_hash_8b)
551	: __clobber_all);
552}
553
554char _license[] SEC("license") = "GPL";
555