@@ -371,4 +371,83 @@ __naked void and_then_at_fp_8(void)
371371" ::: __clobber_all );
372372}
373373
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+
374453char _license [] SEC ("license" ) = "GPL" ;
0 commit comments