@@ -371,4 +371,83 @@ __naked void and_then_at_fp_8(void)
371
371
" ::: __clobber_all );
372
372
}
373
373
374
+ SEC ("xdp" )
375
+ __description ("32-bit spill of 64-bit reg should clear ID" )
376
+ __failure __msg ("math between ctx pointer and 4294967295 is not allowed" )
377
+ __naked void spill_32bit_of_64bit_fail (void )
378
+ {
379
+ asm volatile (" \
380
+ r6 = r1; \
381
+ /* Roll one bit to force the verifier to track both branches. */\
382
+ call %[bpf_get_prandom_u32]; \
383
+ r0 &= 0x8; \
384
+ /* Put a large number into r1. */ \
385
+ r1 = 0xffffffff; \
386
+ r1 <<= 32; \
387
+ r1 += r0; \
388
+ /* Assign an ID to r1. */ \
389
+ r2 = r1; \
390
+ /* 32-bit spill r1 to stack - should clear the ID! */\
391
+ *(u32*)(r10 - 8) = r1; \
392
+ /* 32-bit fill r2 from stack. */ \
393
+ r2 = *(u32*)(r10 - 8); \
394
+ /* Compare r2 with another register to trigger find_equal_scalars.\
395
+ * Having one random bit is important here, otherwise the verifier cuts\
396
+ * the corners. If the ID was mistakenly preserved on spill, this would\
397
+ * cause the verifier to think that r1 is also equal to zero in one of\
398
+ * the branches, and equal to eight on the other branch.\
399
+ */ \
400
+ r3 = 0; \
401
+ if r2 != r3 goto l0_%=; \
402
+ l0_%=: r1 >>= 32; \
403
+ /* At this point, if the verifier thinks that r1 is 0, an out-of-bounds\
404
+ * read will happen, because it actually contains 0xffffffff.\
405
+ */ \
406
+ r6 += r1; \
407
+ r0 = *(u32*)(r6 + 0); \
408
+ exit; \
409
+ " :
410
+ : __imm (bpf_get_prandom_u32 )
411
+ : __clobber_all );
412
+ }
413
+
414
+ SEC ("xdp" )
415
+ __description ("16-bit spill of 32-bit reg should clear ID" )
416
+ __failure __msg ("dereference of modified ctx ptr R6 off=65535 disallowed" )
417
+ __naked void spill_16bit_of_32bit_fail (void )
418
+ {
419
+ asm volatile (" \
420
+ r6 = r1; \
421
+ /* Roll one bit to force the verifier to track both branches. */\
422
+ call %[bpf_get_prandom_u32]; \
423
+ r0 &= 0x8; \
424
+ /* Put a large number into r1. */ \
425
+ w1 = 0xffff0000; \
426
+ r1 += r0; \
427
+ /* Assign an ID to r1. */ \
428
+ r2 = r1; \
429
+ /* 16-bit spill r1 to stack - should clear the ID! */\
430
+ *(u16*)(r10 - 8) = r1; \
431
+ /* 16-bit fill r2 from stack. */ \
432
+ r2 = *(u16*)(r10 - 8); \
433
+ /* Compare r2 with another register to trigger find_equal_scalars.\
434
+ * Having one random bit is important here, otherwise the verifier cuts\
435
+ * the corners. If the ID was mistakenly preserved on spill, this would\
436
+ * cause the verifier to think that r1 is also equal to zero in one of\
437
+ * the branches, and equal to eight on the other branch.\
438
+ */ \
439
+ r3 = 0; \
440
+ if r2 != r3 goto l0_%=; \
441
+ l0_%=: r1 >>= 16; \
442
+ /* At this point, if the verifier thinks that r1 is 0, an out-of-bounds\
443
+ * read will happen, because it actually contains 0xffff.\
444
+ */ \
445
+ r6 += r1; \
446
+ r0 = *(u32*)(r6 + 0); \
447
+ exit; \
448
+ " :
449
+ : __imm (bpf_get_prandom_u32 )
450
+ : __clobber_all );
451
+ }
452
+
374
453
char _license [] SEC ("license" ) = "GPL" ;
0 commit comments