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

source code of linux/tools/testing/selftests/bpf/progs/verifier_bounds_mix_sign_unsign.c