~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/progs/verifier_bounds.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /* Converted from tools/testing/selftests/bpf/verifier/bounds.c */
  3 
  4 #include <linux/bpf.h>
  5 #include <bpf/bpf_helpers.h>
  6 #include "bpf_misc.h"
  7 
  8 struct {
  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 
 15 SEC("socket")
 16 __description("subtraction bounds (map value) variant 1")
 17 __failure __msg("R0 max value is outside of the allowed memory range")
 18 __failure_unpriv
 19 __naked void bounds_map_value_variant_1(void)
 20 {
 21         asm volatile ("                                 \
 22         r1 = 0;                                         \
 23         *(u64*)(r10 - 8) = r1;                          \
 24         r2 = r10;                                       \
 25         r2 += -8;                                       \
 26         r1 = %[map_hash_8b] ll;                         \
 27         call %[bpf_map_lookup_elem];                    \
 28         if r0 == 0 goto l0_%=;                          \
 29         r1 = *(u8*)(r0 + 0);                            \
 30         if r1 > 0xff goto l0_%=;                        \
 31         r3 = *(u8*)(r0 + 1);                            \
 32         if r3 > 0xff goto l0_%=;                        \
 33         r1 -= r3;                                       \
 34         r1 >>= 56;                                      \
 35         r0 += r1;                                       \
 36         r0 = *(u8*)(r0 + 0);                            \
 37         exit;                                           \
 38 l0_%=:  r0 = 0;                                         \
 39         exit;                                           \
 40 "       :
 41         : __imm(bpf_map_lookup_elem),
 42           __imm_addr(map_hash_8b)
 43         : __clobber_all);
 44 }
 45 
 46 SEC("socket")
 47 __description("subtraction bounds (map value) variant 2")
 48 __failure
 49 __msg("R0 min value is negative, either use unsigned index or do a if (index >=0) check.")
 50 __msg_unpriv("R1 has unknown scalar with mixed signed bounds")
 51 __naked void bounds_map_value_variant_2(void)
 52 {
 53         asm volatile ("                                 \
 54         r1 = 0;                                         \
 55         *(u64*)(r10 - 8) = r1;                          \
 56         r2 = r10;                                       \
 57         r2 += -8;                                       \
 58         r1 = %[map_hash_8b] ll;                         \
 59         call %[bpf_map_lookup_elem];                    \
 60         if r0 == 0 goto l0_%=;                          \
 61         r1 = *(u8*)(r0 + 0);                            \
 62         if r1 > 0xff goto l0_%=;                        \
 63         r3 = *(u8*)(r0 + 1);                            \
 64         if r3 > 0xff goto l0_%=;                        \
 65         r1 -= r3;                                       \
 66         r0 += r1;                                       \
 67         r0 = *(u8*)(r0 + 0);                            \
 68         exit;                                           \
 69 l0_%=:  r0 = 0;                                         \
 70         exit;                                           \
 71 "       :
 72         : __imm(bpf_map_lookup_elem),
 73           __imm_addr(map_hash_8b)
 74         : __clobber_all);
 75 }
 76 
 77 SEC("socket")
 78 __description("check subtraction on pointers for unpriv")
 79 __success __failure_unpriv __msg_unpriv("R9 pointer -= pointer prohibited")
 80 __retval(0)
 81 __naked void subtraction_on_pointers_for_unpriv(void)
 82 {
 83         asm volatile ("                                 \
 84         r0 = 0;                                         \
 85         r1 = %[map_hash_8b] ll;                         \
 86         r2 = r10;                                       \
 87         r2 += -8;                                       \
 88         r6 = 9;                                         \
 89         *(u64*)(r2 + 0) = r6;                           \
 90         call %[bpf_map_lookup_elem];                    \
 91         r9 = r10;                                       \
 92         r9 -= r0;                                       \
 93         r1 = %[map_hash_8b] ll;                         \
 94         r2 = r10;                                       \
 95         r2 += -8;                                       \
 96         r6 = 0;                                         \
 97         *(u64*)(r2 + 0) = r6;                           \
 98         call %[bpf_map_lookup_elem];                    \
 99         if r0 != 0 goto l0_%=;                          \
100         exit;                                           \
101 l0_%=:  *(u64*)(r0 + 0) = r9;                           \
102         r0 = 0;                                         \
103         exit;                                           \
104 "       :
105         : __imm(bpf_map_lookup_elem),
106           __imm_addr(map_hash_8b)
107         : __clobber_all);
108 }
109 
110 SEC("socket")
111 __description("bounds check based on zero-extended MOV")
112 __success __success_unpriv __retval(0)
113 __naked void based_on_zero_extended_mov(void)
114 {
115         asm volatile ("                                 \
116         r1 = 0;                                         \
117         *(u64*)(r10 - 8) = r1;                          \
118         r2 = r10;                                       \
119         r2 += -8;                                       \
120         r1 = %[map_hash_8b] ll;                         \
121         call %[bpf_map_lookup_elem];                    \
122         if r0 == 0 goto l0_%=;                          \
123         /* r2 = 0x0000'0000'ffff'ffff */                \
124         w2 = 0xffffffff;                                \
125         /* r2 = 0 */                                    \
126         r2 >>= 32;                                      \
127         /* no-op */                                     \
128         r0 += r2;                                       \
129         /* access at offset 0 */                        \
130         r0 = *(u8*)(r0 + 0);                            \
131 l0_%=:  /* exit */                                      \
132         r0 = 0;                                         \
133         exit;                                           \
134 "       :
135         : __imm(bpf_map_lookup_elem),
136           __imm_addr(map_hash_8b)
137         : __clobber_all);
138 }
139 
140 SEC("socket")
141 __description("bounds check based on sign-extended MOV. test1")
142 __failure __msg("map_value pointer and 4294967295")
143 __failure_unpriv
144 __naked void on_sign_extended_mov_test1(void)
145 {
146         asm volatile ("                                 \
147         r1 = 0;                                         \
148         *(u64*)(r10 - 8) = r1;                          \
149         r2 = r10;                                       \
150         r2 += -8;                                       \
151         r1 = %[map_hash_8b] ll;                         \
152         call %[bpf_map_lookup_elem];                    \
153         if r0 == 0 goto l0_%=;                          \
154         /* r2 = 0xffff'ffff'ffff'ffff */                \
155         r2 = 0xffffffff;                                \
156         /* r2 = 0xffff'ffff */                          \
157         r2 >>= 32;                                      \
158         /* r0 = <oob pointer> */                        \
159         r0 += r2;                                       \
160         /* access to OOB pointer */                     \
161         r0 = *(u8*)(r0 + 0);                            \
162 l0_%=:  /* exit */                                      \
163         r0 = 0;                                         \
164         exit;                                           \
165 "       :
166         : __imm(bpf_map_lookup_elem),
167           __imm_addr(map_hash_8b)
168         : __clobber_all);
169 }
170 
171 SEC("socket")
172 __description("bounds check based on sign-extended MOV. test2")
173 __failure __msg("R0 min value is outside of the allowed memory range")
174 __failure_unpriv
175 __naked void on_sign_extended_mov_test2(void)
176 {
177         asm volatile ("                                 \
178         r1 = 0;                                         \
179         *(u64*)(r10 - 8) = r1;                          \
180         r2 = r10;                                       \
181         r2 += -8;                                       \
182         r1 = %[map_hash_8b] ll;                         \
183         call %[bpf_map_lookup_elem];                    \
184         if r0 == 0 goto l0_%=;                          \
185         /* r2 = 0xffff'ffff'ffff'ffff */                \
186         r2 = 0xffffffff;                                \
187         /* r2 = 0xfff'ffff */                           \
188         r2 >>= 36;                                      \
189         /* r0 = <oob pointer> */                        \
190         r0 += r2;                                       \
191         /* access to OOB pointer */                     \
192         r0 = *(u8*)(r0 + 0);                            \
193 l0_%=:  /* exit */                                      \
194         r0 = 0;                                         \
195         exit;                                           \
196 "       :
197         : __imm(bpf_map_lookup_elem),
198           __imm_addr(map_hash_8b)
199         : __clobber_all);
200 }
201 
202 SEC("tc")
203 __description("bounds check based on reg_off + var_off + insn_off. test1")
204 __failure __msg("value_size=8 off=1073741825")
205 __naked void var_off_insn_off_test1(void)
206 {
207         asm volatile ("                                 \
208         r6 = *(u32*)(r1 + %[__sk_buff_mark]);           \
209         r1 = 0;                                         \
210         *(u64*)(r10 - 8) = r1;                          \
211         r2 = r10;                                       \
212         r2 += -8;                                       \
213         r1 = %[map_hash_8b] ll;                         \
214         call %[bpf_map_lookup_elem];                    \
215         if r0 == 0 goto l0_%=;                          \
216         r6 &= 1;                                        \
217         r6 += %[__imm_0];                               \
218         r0 += r6;                                       \
219         r0 += %[__imm_0];                               \
220 l0_%=:  r0 = *(u8*)(r0 + 3);                            \
221         r0 = 0;                                         \
222         exit;                                           \
223 "       :
224         : __imm(bpf_map_lookup_elem),
225           __imm_addr(map_hash_8b),
226           __imm_const(__imm_0, (1 << 29) - 1),
227           __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
228         : __clobber_all);
229 }
230 
231 SEC("tc")
232 __description("bounds check based on reg_off + var_off + insn_off. test2")
233 __failure __msg("value 1073741823")
234 __naked void var_off_insn_off_test2(void)
235 {
236         asm volatile ("                                 \
237         r6 = *(u32*)(r1 + %[__sk_buff_mark]);           \
238         r1 = 0;                                         \
239         *(u64*)(r10 - 8) = r1;                          \
240         r2 = r10;                                       \
241         r2 += -8;                                       \
242         r1 = %[map_hash_8b] ll;                         \
243         call %[bpf_map_lookup_elem];                    \
244         if r0 == 0 goto l0_%=;                          \
245         r6 &= 1;                                        \
246         r6 += %[__imm_0];                               \
247         r0 += r6;                                       \
248         r0 += %[__imm_1];                               \
249 l0_%=:  r0 = *(u8*)(r0 + 3);                            \
250         r0 = 0;                                         \
251         exit;                                           \
252 "       :
253         : __imm(bpf_map_lookup_elem),
254           __imm_addr(map_hash_8b),
255           __imm_const(__imm_0, (1 << 30) - 1),
256           __imm_const(__imm_1, (1 << 29) - 1),
257           __imm_const(__sk_buff_mark, offsetof(struct __sk_buff, mark))
258         : __clobber_all);
259 }
260 
261 SEC("socket")
262 __description("bounds check after truncation of non-boundary-crossing range")
263 __success __success_unpriv __retval(0)
264 __naked void of_non_boundary_crossing_range(void)
265 {
266         asm volatile ("                                 \
267         r1 = 0;                                         \
268         *(u64*)(r10 - 8) = r1;                          \
269         r2 = r10;                                       \
270         r2 += -8;                                       \
271         r1 = %[map_hash_8b] ll;                         \
272         call %[bpf_map_lookup_elem];                    \
273         if r0 == 0 goto l0_%=;                          \
274         /* r1 = [0x00, 0xff] */                         \
275         r1 = *(u8*)(r0 + 0);                            \
276         r2 = 1;                                         \
277         /* r2 = 0x10'0000'0000 */                       \
278         r2 <<= 36;                                      \
279         /* r1 = [0x10'0000'0000, 0x10'0000'00ff] */     \
280         r1 += r2;                                       \
281         /* r1 = [0x10'7fff'ffff, 0x10'8000'00fe] */     \
282         r1 += 0x7fffffff;                               \
283         /* r1 = [0x00, 0xff] */                         \
284         w1 -= 0x7fffffff;                               \
285         /* r1 = 0 */                                    \
286         r1 >>= 8;                                       \
287         /* no-op */                                     \
288         r0 += r1;                                       \
289         /* access at offset 0 */                        \
290         r0 = *(u8*)(r0 + 0);                            \
291 l0_%=:  /* exit */                                      \
292         r0 = 0;                                         \
293         exit;                                           \
294 "       :
295         : __imm(bpf_map_lookup_elem),
296           __imm_addr(map_hash_8b)
297         : __clobber_all);
298 }
299 
300 SEC("socket")
301 __description("bounds check after truncation of boundary-crossing range (1)")
302 __failure
303 /* not actually fully unbounded, but the bound is very high */
304 __msg("value -4294967168 makes map_value pointer be out of bounds")
305 __failure_unpriv
306 __naked void of_boundary_crossing_range_1(void)
307 {
308         asm volatile ("                                 \
309         r1 = 0;                                         \
310         *(u64*)(r10 - 8) = r1;                          \
311         r2 = r10;                                       \
312         r2 += -8;                                       \
313         r1 = %[map_hash_8b] ll;                         \
314         call %[bpf_map_lookup_elem];                    \
315         if r0 == 0 goto l0_%=;                          \
316         /* r1 = [0x00, 0xff] */                         \
317         r1 = *(u8*)(r0 + 0);                            \
318         r1 += %[__imm_0];                               \
319         /* r1 = [0xffff'ff80, 0x1'0000'007f] */         \
320         r1 += %[__imm_0];                               \
321         /* r1 = [0xffff'ff80, 0xffff'ffff] or           \
322          *      [0x0000'0000, 0x0000'007f]              \
323          */                                             \
324         w1 += 0;                                        \
325         r1 -= %[__imm_0];                               \
326         /* r1 = [0x00, 0xff] or                         \
327          *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]\
328          */                                             \
329         r1 -= %[__imm_0];                               \
330         /* error on OOB pointer computation */          \
331         r0 += r1;                                       \
332         /* exit */                                      \
333         r0 = 0;                                         \
334 l0_%=:  exit;                                           \
335 "       :
336         : __imm(bpf_map_lookup_elem),
337           __imm_addr(map_hash_8b),
338           __imm_const(__imm_0, 0xffffff80 >> 1)
339         : __clobber_all);
340 }
341 
342 SEC("socket")
343 __description("bounds check after truncation of boundary-crossing range (2)")
344 __failure __msg("value -4294967168 makes map_value pointer be out of bounds")
345 __failure_unpriv
346 __naked void of_boundary_crossing_range_2(void)
347 {
348         asm volatile ("                                 \
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 = [0x00, 0xff] */                         \
357         r1 = *(u8*)(r0 + 0);                            \
358         r1 += %[__imm_0];                               \
359         /* r1 = [0xffff'ff80, 0x1'0000'007f] */         \
360         r1 += %[__imm_0];                               \
361         /* r1 = [0xffff'ff80, 0xffff'ffff] or           \
362          *      [0x0000'0000, 0x0000'007f]              \
363          * difference to previous test: truncation via MOV32\
364          * instead of ALU32.                            \
365          */                                             \
366         w1 = w1;                                        \
367         r1 -= %[__imm_0];                               \
368         /* r1 = [0x00, 0xff] or                         \
369          *      [0xffff'ffff'0000'0080, 0xffff'ffff'ffff'ffff]\
370          */                                             \
371         r1 -= %[__imm_0];                               \
372         /* error on OOB pointer computation */          \
373         r0 += r1;                                       \
374         /* exit */                                      \
375         r0 = 0;                                         \
376 l0_%=:  exit;                                           \
377 "       :
378         : __imm(bpf_map_lookup_elem),
379           __imm_addr(map_hash_8b),
380           __imm_const(__imm_0, 0xffffff80 >> 1)
381         : __clobber_all);
382 }
383 
384 SEC("socket")
385 __description("bounds check after wrapping 32-bit addition")
386 __success __success_unpriv __retval(0)
387 __naked void after_wrapping_32_bit_addition(void)
388 {
389         asm volatile ("                                 \
390         r1 = 0;                                         \
391         *(u64*)(r10 - 8) = r1;                          \
392         r2 = r10;                                       \
393         r2 += -8;                                       \
394         r1 = %[map_hash_8b] ll;                         \
395         call %[bpf_map_lookup_elem];                    \
396         if r0 == 0 goto l0_%=;                          \
397         /* r1 = 0x7fff'ffff */                          \
398         r1 = 0x7fffffff;                                \
399         /* r1 = 0xffff'fffe */                          \
400         r1 += 0x7fffffff;                               \
401         /* r1 = 0 */                                    \
402         w1 += 2;                                        \
403         /* no-op */                                     \
404         r0 += r1;                                       \
405         /* access at offset 0 */                        \
406         r0 = *(u8*)(r0 + 0);                            \
407 l0_%=:  /* exit */                                      \
408         r0 = 0;                                         \
409         exit;                                           \
410 "       :
411         : __imm(bpf_map_lookup_elem),
412           __imm_addr(map_hash_8b)
413         : __clobber_all);
414 }
415 
416 SEC("socket")
417 __description("bounds check after shift with oversized count operand")
418 __failure __msg("R0 max value is outside of the allowed memory range")
419 __failure_unpriv
420 __naked void shift_with_oversized_count_operand(void)
421 {
422         asm volatile ("                                 \
423         r1 = 0;                                         \
424         *(u64*)(r10 - 8) = r1;                          \
425         r2 = r10;                                       \
426         r2 += -8;                                       \
427         r1 = %[map_hash_8b] ll;                         \
428         call %[bpf_map_lookup_elem];                    \
429         if r0 == 0 goto l0_%=;                          \
430         r2 = 32;                                        \
431         r1 = 1;                                         \
432         /* r1 = (u32)1 << (u32)32 = ? */                \
433         w1 <<= w2;                                      \
434         /* r1 = [0x0000, 0xffff] */                     \
435         r1 &= 0xffff;                                   \
436         /* computes unknown pointer, potentially OOB */ \
437         r0 += r1;                                       \
438         /* potentially OOB access */                    \
439         r0 = *(u8*)(r0 + 0);                            \
440 l0_%=:  /* exit */                                      \
441         r0 = 0;                                         \
442         exit;                                           \
443 "       :
444         : __imm(bpf_map_lookup_elem),
445           __imm_addr(map_hash_8b)
446         : __clobber_all);
447 }
448 
449 SEC("socket")
450 __description("bounds check after right shift of maybe-negative number")
451 __failure __msg("R0 unbounded memory access")
452 __failure_unpriv
453 __naked void shift_of_maybe_negative_number(void)
454 {
455         asm volatile ("                                 \
456         r1 = 0;                                         \
457         *(u64*)(r10 - 8) = r1;                          \
458         r2 = r10;                                       \
459         r2 += -8;                                       \
460         r1 = %[map_hash_8b] ll;                         \
461         call %[bpf_map_lookup_elem];                    \
462         if r0 == 0 goto l0_%=;                          \
463         /* r1 = [0x00, 0xff] */                         \
464         r1 = *(u8*)(r0 + 0);                            \
465         /* r1 = [-0x01, 0xfe] */                        \
466         r1 -= 1;                                        \
467         /* r1 = 0 or 0xff'ffff'ffff'ffff */             \
468         r1 >>= 8;                                       \
469         /* r1 = 0 or 0xffff'ffff'ffff */                \
470         r1 >>= 8;                                       \
471         /* computes unknown pointer, potentially OOB */ \
472         r0 += r1;                                       \
473         /* potentially OOB access */                    \
474         r0 = *(u8*)(r0 + 0);                            \
475 l0_%=:  /* exit */                                      \
476         r0 = 0;                                         \
477         exit;                                           \
478 "       :
479         : __imm(bpf_map_lookup_elem),
480           __imm_addr(map_hash_8b)
481         : __clobber_all);
482 }
483 
484 SEC("socket")
485 __description("bounds check after 32-bit right shift with 64-bit input")
486 __failure __msg("math between map_value pointer and 4294967294 is not allowed")
487 __failure_unpriv
488 __naked void shift_with_64_bit_input(void)
489 {
490         asm volatile ("                                 \
491         r1 = 0;                                         \
492         *(u64*)(r10 - 8) = r1;                          \
493         r2 = r10;                                       \
494         r2 += -8;                                       \
495         r1 = %[map_hash_8b] ll;                         \
496         call %[bpf_map_lookup_elem];                    \
497         if r0 == 0 goto l0_%=;                          \
498         r1 = 2;                                         \
499         /* r1 = 1<<32 */                                \
500         r1 <<= 31;                                      \
501         /* r1 = 0 (NOT 2!) */                           \
502         w1 >>= 31;                                      \
503         /* r1 = 0xffff'fffe (NOT 0!) */                 \
504         w1 -= 2;                                        \
505         /* error on computing OOB pointer */            \
506         r0 += r1;                                       \
507         /* exit */                                      \
508         r0 = 0;                                         \
509 l0_%=:  exit;                                           \
510 "       :
511         : __imm(bpf_map_lookup_elem),
512           __imm_addr(map_hash_8b)
513         : __clobber_all);
514 }
515 
516 SEC("socket")
517 __description("bounds check map access with off+size signed 32bit overflow. test1")
518 __failure __msg("map_value pointer and 2147483646")
519 __failure_unpriv
520 __naked void size_signed_32bit_overflow_test1(void)
521 {
522         asm volatile ("                                 \
523         r1 = 0;                                         \
524         *(u64*)(r10 - 8) = r1;                          \
525         r2 = r10;                                       \
526         r2 += -8;                                       \
527         r1 = %[map_hash_8b] ll;                         \
528         call %[bpf_map_lookup_elem];                    \
529         if r0 != 0 goto l0_%=;                          \
530         exit;                                           \
531 l0_%=:  r0 += 0x7ffffffe;                               \
532         r0 = *(u64*)(r0 + 0);                           \
533         goto l1_%=;                                     \
534 l1_%=:  exit;                                           \
535 "       :
536         : __imm(bpf_map_lookup_elem),
537           __imm_addr(map_hash_8b)
538         : __clobber_all);
539 }
540 
541 SEC("socket")
542 __description("bounds check map access with off+size signed 32bit overflow. test2")
543 __failure __msg("pointer offset 1073741822")
544 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
545 __naked void size_signed_32bit_overflow_test2(void)
546 {
547         asm volatile ("                                 \
548         r1 = 0;                                         \
549         *(u64*)(r10 - 8) = r1;                          \
550         r2 = r10;                                       \
551         r2 += -8;                                       \
552         r1 = %[map_hash_8b] ll;                         \
553         call %[bpf_map_lookup_elem];                    \
554         if r0 != 0 goto l0_%=;                          \
555         exit;                                           \
556 l0_%=:  r0 += 0x1fffffff;                               \
557         r0 += 0x1fffffff;                               \
558         r0 += 0x1fffffff;                               \
559         r0 = *(u64*)(r0 + 0);                           \
560         goto l1_%=;                                     \
561 l1_%=:  exit;                                           \
562 "       :
563         : __imm(bpf_map_lookup_elem),
564           __imm_addr(map_hash_8b)
565         : __clobber_all);
566 }
567 
568 SEC("socket")
569 __description("bounds check map access with off+size signed 32bit overflow. test3")
570 __failure __msg("pointer offset -1073741822")
571 __msg_unpriv("R0 pointer arithmetic of map value goes out of range")
572 __naked void size_signed_32bit_overflow_test3(void)
573 {
574         asm volatile ("                                 \
575         r1 = 0;                                         \
576         *(u64*)(r10 - 8) = r1;                          \
577         r2 = r10;                                       \
578         r2 += -8;                                       \
579         r1 = %[map_hash_8b] ll;                         \
580         call %[bpf_map_lookup_elem];                    \
581         if r0 != 0 goto l0_%=;                          \
582         exit;                                           \
583 l0_%=:  r0 -= 0x1fffffff;                               \
584         r0 -= 0x1fffffff;                               \
585         r0 = *(u64*)(r0 + 2);                           \
586         goto l1_%=;                                     \
587 l1_%=:  exit;                                           \
588 "       :
589         : __imm(bpf_map_lookup_elem),
590           __imm_addr(map_hash_8b)
591         : __clobber_all);
592 }
593 
594 SEC("socket")
595 __description("bounds check map access with off+size signed 32bit overflow. test4")
596 __failure __msg("map_value pointer and 1000000000000")
597 __failure_unpriv
598 __naked void size_signed_32bit_overflow_test4(void)
599 {
600         asm volatile ("                                 \
601         r1 = 0;                                         \
602         *(u64*)(r10 - 8) = r1;                          \
603         r2 = r10;                                       \
604         r2 += -8;                                       \
605         r1 = %[map_hash_8b] ll;                         \
606         call %[bpf_map_lookup_elem];                    \
607         if r0 != 0 goto l0_%=;                          \
608         exit;                                           \
609 l0_%=:  r1 = 1000000;                                   \
610         r1 *= 1000000;                                  \
611         r0 += r1;                                       \
612         r0 = *(u64*)(r0 + 2);                           \
613         goto l1_%=;                                     \
614 l1_%=:  exit;                                           \
615 "       :
616         : __imm(bpf_map_lookup_elem),
617           __imm_addr(map_hash_8b)
618         : __clobber_all);
619 }
620 
621 SEC("socket")
622 __description("bounds check mixed 32bit and 64bit arithmetic. test1")
623 __success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
624 __retval(0)
625 __naked void _32bit_and_64bit_arithmetic_test1(void)
626 {
627         asm volatile ("                                 \
628         r0 = 0;                                         \
629         r1 = -1;                                        \
630         r1 <<= 32;                                      \
631         r1 += 1;                                        \
632         /* r1 = 0xffffFFFF00000001 */                   \
633         if w1 > 1 goto l0_%=;                           \
634         /* check ALU64 op keeps 32bit bounds */         \
635         r1 += 1;                                        \
636         if w1 > 2 goto l0_%=;                           \
637         goto l1_%=;                                     \
638 l0_%=:  /* invalid ldx if bounds are lost above */      \
639         r0 = *(u64*)(r0 - 1);                           \
640 l1_%=:  exit;                                           \
641 "       ::: __clobber_all);
642 }
643 
644 SEC("socket")
645 __description("bounds check mixed 32bit and 64bit arithmetic. test2")
646 __success __failure_unpriv __msg_unpriv("R0 invalid mem access 'scalar'")
647 __retval(0)
648 __naked void _32bit_and_64bit_arithmetic_test2(void)
649 {
650         asm volatile ("                                 \
651         r0 = 0;                                         \
652         r1 = -1;                                        \
653         r1 <<= 32;                                      \
654         r1 += 1;                                        \
655         /* r1 = 0xffffFFFF00000001 */                   \
656         r2 = 3;                                         \
657         /* r1 = 0x2 */                                  \
658         w1 += 1;                                        \
659         /* check ALU32 op zero extends 64bit bounds */  \
660         if r1 > r2 goto l0_%=;                          \
661         goto l1_%=;                                     \
662 l0_%=:  /* invalid ldx if bounds are lost above */      \
663         r0 = *(u64*)(r0 - 1);                           \
664 l1_%=:  exit;                                           \
665 "       ::: __clobber_all);
666 }
667 
668 SEC("tc")
669 __description("assigning 32bit bounds to 64bit for wA = 0, wB = wA")
670 __success __retval(0) __flag(BPF_F_ANY_ALIGNMENT)
671 __naked void for_wa_0_wb_wa(void)
672 {
673         asm volatile ("                                 \
674         r8 = *(u32*)(r1 + %[__sk_buff_data_end]);       \
675         r7 = *(u32*)(r1 + %[__sk_buff_data]);           \
676         w9 = 0;                                         \
677         w2 = w9;                                        \
678         r6 = r7;                                        \
679         r6 += r2;                                       \
680         r3 = r6;                                        \
681         r3 += 8;                                        \
682         if r3 > r8 goto l0_%=;                          \
683         r5 = *(u32*)(r6 + 0);                           \
684 l0_%=:  r0 = 0;                                         \
685         exit;                                           \
686 "       :
687         : __imm_const(__sk_buff_data, offsetof(struct __sk_buff, data)),
688           __imm_const(__sk_buff_data_end, offsetof(struct __sk_buff, data_end))
689         : __clobber_all);
690 }
691 
692 SEC("socket")
693 __description("bounds check for reg = 0, reg xor 1")
694 __success __failure_unpriv
695 __msg_unpriv("R0 min value is outside of the allowed memory range")
696 __retval(0)
697 __naked void reg_0_reg_xor_1(void)
698 {
699         asm volatile ("                                 \
700         r1 = 0;                                         \
701         *(u64*)(r10 - 8) = r1;                          \
702         r2 = r10;                                       \
703         r2 += -8;                                       \
704         r1 = %[map_hash_8b] ll;                         \
705         call %[bpf_map_lookup_elem];                    \
706         if r0 != 0 goto l0_%=;                          \
707         exit;                                           \
708 l0_%=:  r1 = 0;                                         \
709         r1 ^= 1;                                        \
710         if r1 != 0 goto l1_%=;                          \
711         r0 = *(u64*)(r0 + 8);                           \
712 l1_%=:  r0 = 0;                                         \
713         exit;                                           \
714 "       :
715         : __imm(bpf_map_lookup_elem),
716           __imm_addr(map_hash_8b)
717         : __clobber_all);
718 }
719 
720 SEC("socket")
721 __description("bounds check for reg32 = 0, reg32 xor 1")
722 __success __failure_unpriv
723 __msg_unpriv("R0 min value is outside of the allowed memory range")
724 __retval(0)
725 __naked void reg32_0_reg32_xor_1(void)
726 {
727         asm volatile ("                                 \
728         r1 = 0;                                         \
729         *(u64*)(r10 - 8) = r1;                          \
730         r2 = r10;                                       \
731         r2 += -8;                                       \
732         r1 = %[map_hash_8b] ll;                         \
733         call %[bpf_map_lookup_elem];                    \
734         if r0 != 0 goto l0_%=;                          \
735         exit;                                           \
736 l0_%=:  w1 = 0;                                         \
737         w1 ^= 1;                                        \
738         if w1 != 0 goto l1_%=;                          \
739         r0 = *(u64*)(r0 + 8);                           \
740 l1_%=:  r0 = 0;                                         \
741         exit;                                           \
742 "       :
743         : __imm(bpf_map_lookup_elem),
744           __imm_addr(map_hash_8b)
745         : __clobber_all);
746 }
747 
748 SEC("socket")
749 __description("bounds check for reg = 2, reg xor 3")
750 __success __failure_unpriv
751 __msg_unpriv("R0 min value is outside of the allowed memory range")
752 __retval(0)
753 __naked void reg_2_reg_xor_3(void)
754 {
755         asm volatile ("                                 \
756         r1 = 0;                                         \
757         *(u64*)(r10 - 8) = r1;                          \
758         r2 = r10;                                       \
759         r2 += -8;                                       \
760         r1 = %[map_hash_8b] ll;                         \
761         call %[bpf_map_lookup_elem];                    \
762         if r0 != 0 goto l0_%=;                          \
763         exit;                                           \
764 l0_%=:  r1 = 2;                                         \
765         r1 ^= 3;                                        \
766         if r1 > 0 goto l1_%=;                           \
767         r0 = *(u64*)(r0 + 8);                           \
768 l1_%=:  r0 = 0;                                         \
769         exit;                                           \
770 "       :
771         : __imm(bpf_map_lookup_elem),
772           __imm_addr(map_hash_8b)
773         : __clobber_all);
774 }
775 
776 SEC("socket")
777 __description("bounds check for reg = any, reg xor 3")
778 __failure __msg("invalid access to map value")
779 __msg_unpriv("invalid access to map value")
780 __naked void reg_any_reg_xor_3(void)
781 {
782         asm volatile ("                                 \
783         r1 = 0;                                         \
784         *(u64*)(r10 - 8) = r1;                          \
785         r2 = r10;                                       \
786         r2 += -8;                                       \
787         r1 = %[map_hash_8b] ll;                         \
788         call %[bpf_map_lookup_elem];                    \
789         if r0 != 0 goto l0_%=;                          \
790         exit;                                           \
791 l0_%=:  r1 = *(u64*)(r0 + 0);                           \
792         r1 ^= 3;                                        \
793         if r1 != 0 goto l1_%=;                          \
794         r0 = *(u64*)(r0 + 8);                           \
795 l1_%=:  r0 = 0;                                         \
796         exit;                                           \
797 "       :
798         : __imm(bpf_map_lookup_elem),
799           __imm_addr(map_hash_8b)
800         : __clobber_all);
801 }
802 
803 SEC("socket")
804 __description("bounds check for reg32 = any, reg32 xor 3")
805 __failure __msg("invalid access to map value")
806 __msg_unpriv("invalid access to map value")
807 __naked void reg32_any_reg32_xor_3(void)
808 {
809         asm volatile ("                                 \
810         r1 = 0;                                         \
811         *(u64*)(r10 - 8) = r1;                          \
812         r2 = r10;                                       \
813         r2 += -8;                                       \
814         r1 = %[map_hash_8b] ll;                         \
815         call %[bpf_map_lookup_elem];                    \
816         if r0 != 0 goto l0_%=;                          \
817         exit;                                           \
818 l0_%=:  r1 = *(u64*)(r0 + 0);                           \
819         w1 ^= 3;                                        \
820         if w1 != 0 goto l1_%=;                          \
821         r0 = *(u64*)(r0 + 8);                           \
822 l1_%=:  r0 = 0;                                         \
823         exit;                                           \
824 "       :
825         : __imm(bpf_map_lookup_elem),
826           __imm_addr(map_hash_8b)
827         : __clobber_all);
828 }
829 
830 SEC("socket")
831 __description("bounds check for reg > 0, reg xor 3")
832 __success __failure_unpriv
833 __msg_unpriv("R0 min value is outside of the allowed memory range")
834 __retval(0)
835 __naked void reg_0_reg_xor_3(void)
836 {
837         asm volatile ("                                 \
838         r1 = 0;                                         \
839         *(u64*)(r10 - 8) = r1;                          \
840         r2 = r10;                                       \
841         r2 += -8;                                       \
842         r1 = %[map_hash_8b] ll;                         \
843         call %[bpf_map_lookup_elem];                    \
844         if r0 != 0 goto l0_%=;                          \
845         exit;                                           \
846 l0_%=:  r1 = *(u64*)(r0 + 0);                           \
847         if r1 <= 0 goto l1_%=;                          \
848         r1 ^= 3;                                        \
849         if r1 >= 0 goto l1_%=;                          \
850         r0 = *(u64*)(r0 + 8);                           \
851 l1_%=:  r0 = 0;                                         \
852         exit;                                           \
853 "       :
854         : __imm(bpf_map_lookup_elem),
855           __imm_addr(map_hash_8b)
856         : __clobber_all);
857 }
858 
859 SEC("socket")
860 __description("bounds check for reg32 > 0, reg32 xor 3")
861 __success __failure_unpriv
862 __msg_unpriv("R0 min value is outside of the allowed memory range")
863 __retval(0)
864 __naked void reg32_0_reg32_xor_3(void)
865 {
866         asm volatile ("                                 \
867         r1 = 0;                                         \
868         *(u64*)(r10 - 8) = r1;                          \
869         r2 = r10;                                       \
870         r2 += -8;                                       \
871         r1 = %[map_hash_8b] ll;                         \
872         call %[bpf_map_lookup_elem];                    \
873         if r0 != 0 goto l0_%=;                          \
874         exit;                                           \
875 l0_%=:  r1 = *(u64*)(r0 + 0);                           \
876         if w1 <= 0 goto l1_%=;                          \
877         w1 ^= 3;                                        \
878         if w1 >= 0 goto l1_%=;                          \
879         r0 = *(u64*)(r0 + 8);                           \
880 l1_%=:  r0 = 0;                                         \
881         exit;                                           \
882 "       :
883         : __imm(bpf_map_lookup_elem),
884           __imm_addr(map_hash_8b)
885         : __clobber_all);
886 }
887 
888 SEC("socket")
889 __description("bounds check for non const xor src dst")
890 __success __log_level(2)
891 __msg("5: (af) r0 ^= r6                      ; R0_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=431,var_off=(0x0; 0x1af))")
892 __naked void non_const_xor_src_dst(void)
893 {
894         asm volatile ("                                 \
895         call %[bpf_get_prandom_u32];                    \
896         r6 = r0;                                        \
897         call %[bpf_get_prandom_u32];                    \
898         r6 &= 0xaf;                                     \
899         r0 &= 0x1a0;                                    \
900         r0 ^= r6;                                       \
901         exit;                                           \
902 "       :
903         : __imm(bpf_map_lookup_elem),
904         __imm_addr(map_hash_8b),
905         __imm(bpf_get_prandom_u32)
906         : __clobber_all);
907 }
908 
909 SEC("socket")
910 __description("bounds check for non const or src dst")
911 __success __log_level(2)
912 __msg("5: (4f) r0 |= r6                      ; R0_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=431,var_off=(0x0; 0x1af))")
913 __naked void non_const_or_src_dst(void)
914 {
915         asm volatile ("                                 \
916         call %[bpf_get_prandom_u32];                    \
917         r6 = r0;                                        \
918         call %[bpf_get_prandom_u32];                    \
919         r6 &= 0xaf;                                     \
920         r0 &= 0x1a0;                                    \
921         r0 |= r6;                                       \
922         exit;                                           \
923 "       :
924         : __imm(bpf_map_lookup_elem),
925         __imm_addr(map_hash_8b),
926         __imm(bpf_get_prandom_u32)
927         : __clobber_all);
928 }
929 
930 SEC("socket")
931 __description("bounds check for non const mul regs")
932 __success __log_level(2)
933 __msg("5: (2f) r0 *= r6                      ; R0_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=3825,var_off=(0x0; 0xfff))")
934 __naked void non_const_mul_regs(void)
935 {
936         asm volatile ("                                 \
937         call %[bpf_get_prandom_u32];                    \
938         r6 = r0;                                        \
939         call %[bpf_get_prandom_u32];                    \
940         r6 &= 0xff;                                     \
941         r0 &= 0x0f;                                     \
942         r0 *= r6;                                       \
943         exit;                                           \
944 "       :
945         : __imm(bpf_map_lookup_elem),
946         __imm_addr(map_hash_8b),
947         __imm(bpf_get_prandom_u32)
948         : __clobber_all);
949 }
950 
951 SEC("socket")
952 __description("bounds checks after 32-bit truncation. test 1")
953 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
954 __retval(0)
955 __naked void _32_bit_truncation_test_1(void)
956 {
957         asm volatile ("                                 \
958         r1 = 0;                                         \
959         *(u64*)(r10 - 8) = r1;                          \
960         r2 = r10;                                       \
961         r2 += -8;                                       \
962         r1 = %[map_hash_8b] ll;                         \
963         call %[bpf_map_lookup_elem];                    \
964         if r0 == 0 goto l0_%=;                          \
965         r1 = *(u32*)(r0 + 0);                           \
966         /* This used to reduce the max bound to 0x7fffffff */\
967         if r1 == 0 goto l1_%=;                          \
968         if r1 > 0x7fffffff goto l0_%=;                  \
969 l1_%=:  r0 = 0;                                         \
970 l0_%=:  exit;                                           \
971 "       :
972         : __imm(bpf_map_lookup_elem),
973           __imm_addr(map_hash_8b)
974         : __clobber_all);
975 }
976 
977 SEC("socket")
978 __description("bounds checks after 32-bit truncation. test 2")
979 __success __failure_unpriv __msg_unpriv("R0 leaks addr")
980 __retval(0)
981 __naked void _32_bit_truncation_test_2(void)
982 {
983         asm volatile ("                                 \
984         r1 = 0;                                         \
985         *(u64*)(r10 - 8) = r1;                          \
986         r2 = r10;                                       \
987         r2 += -8;                                       \
988         r1 = %[map_hash_8b] ll;                         \
989         call %[bpf_map_lookup_elem];                    \
990         if r0 == 0 goto l0_%=;                          \
991         r1 = *(u32*)(r0 + 0);                           \
992         if r1 s< 1 goto l1_%=;                          \
993         if w1 s< 0 goto l0_%=;                          \
994 l1_%=:  r0 = 0;                                         \
995 l0_%=:  exit;                                           \
996 "       :
997         : __imm(bpf_map_lookup_elem),
998           __imm_addr(map_hash_8b)
999         : __clobber_all);
1000 }
1001 
1002 SEC("xdp")
1003 __description("bound check with JMP_JLT for crossing 64-bit signed boundary")
1004 __success __retval(0)
1005 __naked void crossing_64_bit_signed_boundary_1(void)
1006 {
1007         asm volatile ("                                 \
1008         r2 = *(u32*)(r1 + %[xdp_md_data]);              \
1009         r3 = *(u32*)(r1 + %[xdp_md_data_end]);          \
1010         r1 = r2;                                        \
1011         r1 += 1;                                        \
1012         if r1 > r3 goto l0_%=;                          \
1013         r1 = *(u8*)(r2 + 0);                            \
1014         r0 = 0x7fffffffffffff10 ll;                     \
1015         r1 += r0;                                       \
1016         r0 = 0x8000000000000000 ll;                     \
1017 l1_%=:  r0 += 1;                                        \
1018         /* r1 unsigned range is [0x7fffffffffffff10, 0x800000000000000f] */\
1019         if r0 < r1 goto l1_%=;                          \
1020 l0_%=:  r0 = 0;                                         \
1021         exit;                                           \
1022 "       :
1023         : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
1024           __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end))
1025         : __clobber_all);
1026 }
1027 
1028 SEC("xdp")
1029 __description("bound check with JMP_JSLT for crossing 64-bit signed boundary")
1030 __success __retval(0)
1031 __flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
1032 __naked void crossing_64_bit_signed_boundary_2(void)
1033 {
1034         asm volatile ("                                 \
1035         r2 = *(u32*)(r1 + %[xdp_md_data]);              \
1036         r3 = *(u32*)(r1 + %[xdp_md_data_end]);          \
1037         r1 = r2;                                        \
1038         r1 += 1;                                        \
1039         if r1 > r3 goto l0_%=;                          \
1040         r1 = *(u8*)(r2 + 0);                            \
1041         r0 = 0x7fffffffffffff10 ll;                     \
1042         r1 += r0;                                       \
1043         r2 = 0x8000000000000fff ll;                     \
1044         r0 = 0x8000000000000000 ll;                     \
1045 l1_%=:  r0 += 1;                                        \
1046         if r0 s> r2 goto l0_%=;                         \
1047         /* r1 signed range is [S64_MIN, S64_MAX] */     \
1048         if r0 s< r1 goto l1_%=;                         \
1049         r0 = 1;                                         \
1050         exit;                                           \
1051 l0_%=:  r0 = 0;                                         \
1052         exit;                                           \
1053 "       :
1054         : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
1055           __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end))
1056         : __clobber_all);
1057 }
1058 
1059 SEC("xdp")
1060 __description("bound check for loop upper bound greater than U32_MAX")
1061 __success __retval(0)
1062 __naked void bound_greater_than_u32_max(void)
1063 {
1064         asm volatile ("                                 \
1065         r2 = *(u32*)(r1 + %[xdp_md_data]);              \
1066         r3 = *(u32*)(r1 + %[xdp_md_data_end]);          \
1067         r1 = r2;                                        \
1068         r1 += 1;                                        \
1069         if r1 > r3 goto l0_%=;                          \
1070         r1 = *(u8*)(r2 + 0);                            \
1071         r0 = 0x100000000 ll;                            \
1072         r1 += r0;                                       \
1073         r0 = 0x100000000 ll;                            \
1074 l1_%=:  r0 += 1;                                        \
1075         if r0 < r1 goto l1_%=;                          \
1076 l0_%=:  r0 = 0;                                         \
1077         exit;                                           \
1078 "       :
1079         : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
1080           __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end))
1081         : __clobber_all);
1082 }
1083 
1084 SEC("xdp")
1085 __description("bound check with JMP32_JLT for crossing 32-bit signed boundary")
1086 __success __retval(0)
1087 __naked void crossing_32_bit_signed_boundary_1(void)
1088 {
1089         asm volatile ("                                 \
1090         r2 = *(u32*)(r1 + %[xdp_md_data]);              \
1091         r3 = *(u32*)(r1 + %[xdp_md_data_end]);          \
1092         r1 = r2;                                        \
1093         r1 += 1;                                        \
1094         if r1 > r3 goto l0_%=;                          \
1095         r1 = *(u8*)(r2 + 0);                            \
1096         w0 = 0x7fffff10;                                \
1097         w1 += w0;                                       \
1098         w0 = 0x80000000;                                \
1099 l1_%=:  w0 += 1;                                        \
1100         /* r1 unsigned range is [0, 0x8000000f] */      \
1101         if w0 < w1 goto l1_%=;                          \
1102 l0_%=:  r0 = 0;                                         \
1103         exit;                                           \
1104 "       :
1105         : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
1106           __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end))
1107         : __clobber_all);
1108 }
1109 
1110 SEC("xdp")
1111 __description("bound check with JMP32_JSLT for crossing 32-bit signed boundary")
1112 __success __retval(0)
1113 __flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
1114 __naked void crossing_32_bit_signed_boundary_2(void)
1115 {
1116         asm volatile ("                                 \
1117         r2 = *(u32*)(r1 + %[xdp_md_data]);              \
1118         r3 = *(u32*)(r1 + %[xdp_md_data_end]);          \
1119         r1 = r2;                                        \
1120         r1 += 1;                                        \
1121         if r1 > r3 goto l0_%=;                          \
1122         r1 = *(u8*)(r2 + 0);                            \
1123         w0 = 0x7fffff10;                                \
1124         w1 += w0;                                       \
1125         w2 = 0x80000fff;                                \
1126         w0 = 0x80000000;                                \
1127 l1_%=:  w0 += 1;                                        \
1128         if w0 s> w2 goto l0_%=;                         \
1129         /* r1 signed range is [S32_MIN, S32_MAX] */     \
1130         if w0 s< w1 goto l1_%=;                         \
1131         r0 = 1;                                         \
1132         exit;                                           \
1133 l0_%=:  r0 = 0;                                         \
1134         exit;                                           \
1135 "       :
1136         : __imm_const(xdp_md_data, offsetof(struct xdp_md, data)),
1137           __imm_const(xdp_md_data_end, offsetof(struct xdp_md, data_end))
1138         : __clobber_all);
1139 }
1140 
1141 SEC("tc")
1142 __description("bounds check with JMP_NE for reg edge")
1143 __success __retval(0)
1144 __naked void reg_not_equal_const(void)
1145 {
1146         asm volatile ("                                 \
1147         r6 = r1;                                        \
1148         r1 = 0;                                         \
1149         *(u64*)(r10 - 8) = r1;                          \
1150         call %[bpf_get_prandom_u32];                    \
1151         r4 = r0;                                        \
1152         r4 &= 7;                                        \
1153         if r4 != 0 goto l0_%=;                          \
1154         r0 = 0;                                         \
1155         exit;                                           \
1156 l0_%=:  r1 = r6;                                        \
1157         r2 = 0;                                         \
1158         r3 = r10;                                       \
1159         r3 += -8;                                       \
1160         r5 = 0;                                         \
1161         /* The 4th argument of bpf_skb_store_bytes is defined as \
1162          * ARG_CONST_SIZE, so 0 is not allowed. The 'r4 != 0' \
1163          * is providing us this exclusion of zero from initial \
1164          * [0, 7] range.                                \
1165          */                                             \
1166         call %[bpf_skb_store_bytes];                    \
1167         r0 = 0;                                         \
1168         exit;                                           \
1169 "       :
1170         : __imm(bpf_get_prandom_u32),
1171           __imm(bpf_skb_store_bytes)
1172         : __clobber_all);
1173 }
1174 
1175 SEC("tc")
1176 __description("bounds check with JMP_EQ for reg edge")
1177 __success __retval(0)
1178 __naked void reg_equal_const(void)
1179 {
1180         asm volatile ("                                 \
1181         r6 = r1;                                        \
1182         r1 = 0;                                         \
1183         *(u64*)(r10 - 8) = r1;                          \
1184         call %[bpf_get_prandom_u32];                    \
1185         r4 = r0;                                        \
1186         r4 &= 7;                                        \
1187         if r4 == 0 goto l0_%=;                          \
1188         r1 = r6;                                        \
1189         r2 = 0;                                         \
1190         r3 = r10;                                       \
1191         r3 += -8;                                       \
1192         r5 = 0;                                         \
1193         /* Just the same as what we do in reg_not_equal_const() */ \
1194         call %[bpf_skb_store_bytes];                    \
1195 l0_%=:  r0 = 0;                                         \
1196         exit;                                           \
1197 "       :
1198         : __imm(bpf_get_prandom_u32),
1199           __imm(bpf_skb_store_bytes)
1200         : __clobber_all);
1201 }
1202 
1203 char _license[] SEC("license") = "GPL";
1204 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php