/* Check that precision marks propagate through scalar IDs. *Registersr{0,1,2}havethesamescalarID. *RangeinformationispropagatedforscalarssharingsameID. *Checkthatprecisionmarkforr0causesprecisionmarksforr{1,2} *whenrangeinformationispropagatedfor'if<reg><op><const>'insn.
*/
SEC("socket")
__success __log_level(2) /* first 'if' branch */
__msg("6: (0f) r3 += r0")
__msg("frame0: regs=r0 stack= before 4: (25) if r1 > 0x7 goto pc+0")
__msg("frame0: parent state regs=r0,r1,r2 stack=:")
__msg("frame0: regs=r0,r1,r2 stack= before 3: (bf) r2 = r0") /* second 'if' branch */
__msg("from 4 to 5: ")
__msg("6: (0f) r3 += r0")
__msg("frame0: regs=r0 stack= before 5: (bf) r3 = r10")
__msg("frame0: regs=r0 stack= before 4: (25) if r1 > 0x7 goto pc+0") /* parent state already has r{0,1,2} as precise */
__msg("frame0: parent state regs= stack=:")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void linked_regs_bpf_k(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == r2.id */ "r1 = r0;" "r2 = r0;" "if r1 > 7 goto +0;" /* force r0 to be precise, this eventually marks r1 and r2 as *preciseaswellbecauseofsharedIDs
*/ "r3 = r10;" "r3 += r0;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
/* Registers r{0,1,2} share same ID when 'if r1 > ...' insn is processed, *checkthatverifiermarksr{1,2}asprecisewhilebacktracking *'ifr1>...'withr0alreadymarked.
*/
SEC("socket")
__success __log_level(2)
__flag(BPF_F_TEST_STATE_FREQ)
__msg("frame0: regs=r0 stack= before 5: (2d) if r1 > r3 goto pc+0")
__msg("frame0: parent state regs=r0,r1,r2,r3 stack=:")
__msg("frame0: regs=r0,r1,r2,r3 stack= before 4: (b7) r3 = 7")
__naked void linked_regs_bpf_x_src(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == r2.id */ "r1 = r0;" "r2 = r0;" "r3 = 7;" "if r1 > r3 goto +0;" /* force r0 to be precise, this eventually marks r1 and r2 as *preciseaswellbecauseofsharedIDs
*/ "r4 = r10;" "r4 += r0;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
/* Registers r{0,1,2} share same ID when 'if r1 > r3' insn is processed, *checkthatverifiermarksr{0,1,2}asprecisewhilebacktracking *'ifr1>r3'withr3alreadymarked.
*/
SEC("socket")
__success __log_level(2)
__flag(BPF_F_TEST_STATE_FREQ)
__msg("frame0: regs=r3 stack= before 5: (2d) if r1 > r3 goto pc+0")
__msg("frame0: parent state regs=r0,r1,r2,r3 stack=:")
__msg("frame0: regs=r0,r1,r2,r3 stack= before 4: (b7) r3 = 7")
__naked void linked_regs_bpf_x_dst(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == r2.id */ "r1 = r0;" "r2 = r0;" "r3 = 7;" "if r1 > r3 goto +0;" /* force r0 to be precise, this eventually marks r1 and r2 as *preciseaswellbecauseofsharedIDs
*/ "r4 = r10;" "r4 += r3;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
/* Same as linked_regs_bpf_k, but break one of the *links,notethatr1isabsentfromregs=...in__msgbelow.
*/
SEC("socket")
__success __log_level(2)
__msg("7: (0f) r3 += r0")
__msg("frame0: regs=r0 stack= before 6: (bf) r3 = r10")
__msg("frame0: parent state regs=r0 stack=:")
__msg("frame0: regs=r0 stack= before 5: (25) if r0 > 0x7 goto pc+0")
__msg("frame0: parent state regs=r0,r2 stack=:")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void linked_regs_broken_link(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == r2.id */ "r1 = r0;" "r2 = r0;" /* break link for r1, this is the only line that differs *comparedtotheprevioustest
*/ "r1 = 0;" "if r0 > 7 goto +0;" /* force r0 to be precise, *thiseventuallymarksr2asprecisebecauseofsharedIDs
*/ "r3 = r10;" "r3 += r0;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
/* Check that precision marks propagate through scalar IDs. *UsethesamescalarIDinmultiplestackframes,checkthat *precisioninformationispropagatedupthecallstack.
*/
SEC("socket")
__success __log_level(2)
__msg("12: (0f) r2 += r1") /* Current state */
__msg("frame2: last_idx 12 first_idx 11 subseq_idx -1 ")
__msg("frame2: regs=r1 stack= before 11: (bf) r2 = r10")
__msg("frame2: parent state regs=r1 stack=")
__msg("frame1: parent state regs= stack=")
__msg("frame0: parent state regs= stack=") /* Parent state */
__msg("frame2: last_idx 10 first_idx 10 subseq_idx 11 ")
__msg("frame2: regs=r1 stack= before 10: (25) if r1 > 0x7 goto pc+0")
__msg("frame2: parent state regs=r1 stack=") /* frame1.r{6,7} are marked because mark_precise_scalar_ids() *looksforallregisterswithframe2.r1.idinthecurrentstate
*/
__msg("frame1: parent state regs=r6,r7 stack=")
__msg("frame0: parent state regs=r6 stack=") /* Parent state */
__msg("frame2: last_idx 8 first_idx 8 subseq_idx 10")
__msg("frame2: regs=r1 stack= before 8: (85) call pc+1") /* frame1.r1 is marked because of backtracking of call instruction */
__msg("frame1: parent state regs=r1,r6,r7 stack=")
__msg("frame0: parent state regs=r6 stack=") /* Parent state */
__msg("frame1: last_idx 7 first_idx 6 subseq_idx 8")
__msg("frame1: regs=r1,r6,r7 stack= before 7: (bf) r7 = r1")
__msg("frame1: regs=r1,r6 stack= before 6: (bf) r6 = r1")
__msg("frame1: parent state regs=r1 stack=")
__msg("frame0: parent state regs=r6 stack=") /* Parent state */
__msg("frame1: last_idx 4 first_idx 4 subseq_idx 6")
__msg("frame1: regs=r1 stack= before 4: (85) call pc+1")
__msg("frame0: parent state regs=r1,r6 stack=") /* Parent state */
__msg("frame0: last_idx 3 first_idx 1 subseq_idx 4")
__msg("frame0: regs=r1,r6 stack= before 3: (bf) r6 = r0")
__msg("frame0: regs=r0,r1 stack= before 2: (bf) r1 = r0")
__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void precision_many_frames(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == r6.id */ "r1 = r0;" "r6 = r0;" "call precision_many_frames__foo;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
static __naked __noinline __used void precision_many_frames__foo(void)
{ asmvolatile ( /* conflate one of the register numbers (r6) with outer frame, *toverifythatthosearetrackedindependently
*/ "r6 = r1;" "r7 = r1;" "call precision_many_frames__bar;" "exit"
::: __clobber_all);
}
static __naked __noinline __used void precision_many_frames__bar(void)
{ asmvolatile ( "if r1 > 7 goto +0;" /* force r1 to be precise, this eventually marks: *-barframer1 *-fooframer{1,6,7} *-mainframer{1,6}
*/ "r2 = r10;" "r2 += r1;" "r0 = 0;" "exit;"
::: __clobber_all);
}
/* Check that scalars with the same IDs are marked precise on stack as *wellasinregisters.
*/
SEC("socket")
__success __log_level(2)
__msg("11: (0f) r2 += r1") /* foo frame */
__msg("frame1: regs=r1 stack= before 10: (bf) r2 = r10")
__msg("frame1: regs=r1 stack= before 9: (25) if r1 > 0x7 goto pc+0")
__msg("frame1: regs=r1 stack=-8,-16 before 8: (7b) *(u64 *)(r10 -16) = r1")
__msg("frame1: regs=r1 stack=-8 before 7: (7b) *(u64 *)(r10 -8) = r1")
__msg("frame1: regs=r1 stack= before 4: (85) call pc+2") /* main frame */
__msg("frame0: regs=r1 stack=-8 before 3: (7b) *(u64 *)(r10 -8) = r1")
__msg("frame0: regs=r1 stack= before 2: (bf) r1 = r0")
__msg("frame0: regs=r0 stack= before 1: (57) r0 &= 255")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void precision_stack(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id == fp[-8].id */ "r1 = r0;" "*(u64*)(r10 - 8) = r1;" "call precision_stack__foo;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
static __naked __noinline __used void precision_stack__foo(void)
{ asmvolatile ( /* conflate one of the register numbers (r6) with outer frame, *toverifythatthosearetrackedindependently
*/ "*(u64*)(r10 - 8) = r1;" "*(u64*)(r10 - 16) = r1;" "if r1 > 7 goto +0;" /* force r1 to be precise, this eventually marks: *-fooframer1,fp{-8,-16} *-mainframer1,fp{-8}
*/ "r2 = r10;" "r2 += r1;" "exit"
::: __clobber_all);
}
/* Use two separate scalar IDs to check that these are propagated *independently.
*/
SEC("socket")
__success __log_level(2) /* r{6,7} */
__msg("12: (0f) r3 += r7")
__msg("frame0: regs=r7 stack= before 11: (bf) r3 = r10")
__msg("frame0: regs=r7 stack= before 9: (25) if r7 > 0x7 goto pc+0") /* ... skip some insns ... */
__msg("frame0: regs=r6,r7 stack= before 3: (bf) r7 = r0")
__msg("frame0: regs=r0,r6 stack= before 2: (bf) r6 = r0") /* r{8,9} */
__msg("13: (0f) r3 += r9")
__msg("frame0: regs=r9 stack= before 12: (0f) r3 += r7") /* ... skip some insns ... */
__msg("frame0: regs=r9 stack= before 10: (25) if r9 > 0x7 goto pc+0")
__msg("frame0: regs=r8,r9 stack= before 7: (bf) r9 = r0")
__msg("frame0: regs=r0,r8 stack= before 6: (bf) r8 = r0")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void precision_two_ids(void)
{ asmvolatile ( /* r6 = random number up to 0xff *r6.id==r7.id
*/ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" "r6 = r0;" "r7 = r0;" /* same, but for r{8,9} */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" "r8 = r0;" "r9 = r0;" /* clear r0 id */ "r0 = 0;" /* propagate equal scalars precision */ "if r7 > 7 goto +0;" "if r9 > 7 goto +0;" "r3 = r10;" /* force r7 to be precise, this also marks r6 */ "r3 += r7;" /* force r9 to be precise, this also marks r8 */ "r3 += r9;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
SEC("socket")
__success __log_level(2)
__flag(BPF_F_TEST_STATE_FREQ) /* check that r0 and r6 have different IDs after 'if', *collect_linked_regs()can'ttiemorethan6registersforasingleinsn.
*/
__msg("8: (25) if r0 > 0x7 goto pc+0 ; R0=scalar(id=1")
__msg("9: (bf) r6 = r6 ; R6_w=scalar(id=2") /* check that r{0-5} are marked precise after 'if' */
__msg("frame0: regs=r0 stack= before 8: (25) if r0 > 0x7 goto pc+0")
__msg("frame0: parent state regs=r0,r1,r2,r3,r4,r5 stack=:")
__naked void linked_regs_too_many_regs(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r{0-6} IDs */ "r1 = r0;" "r2 = r0;" "r3 = r0;" "r4 = r0;" "r5 = r0;" "r6 = r0;" /* propagate range for r{0-6} */ "if r0 > 7 goto +0;" /* make r6 appear in the log */ "r6 = r6;" /* force r0 to be precise, *thiswouldcauser{0-4}tobeprecisebecauseofsharedIDs
*/ "r7 = r10;" "r7 += r0;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
SEC("socket")
__failure __log_level(2)
__flag(BPF_F_TEST_STATE_FREQ)
__msg("regs=r7 stack= before 5: (3d) if r8 >= r0")
__msg("parent state regs=r0,r7,r8")
__msg("regs=r0,r7,r8 stack= before 4: (25) if r0 > 0x1")
__msg("div by zero")
__naked void linked_regs_broken_link_2(void)
{ asmvolatile ( "call %[bpf_get_prandom_u32];" "r7 = r0;" "r8 = r0;" "call %[bpf_get_prandom_u32];" "if r0 > 1 goto +0;" /* r7.id == r8.id, *thusr7precisionimpliesr8precision, *whichimpliesr0precisionbecauseoftheconditionalbelow.
*/ "if r8 >= r0 goto 1f;" /* break id relation between r7 and r8 */ "r8 += r8;" /* make r7 precise */ "if r7 == 0 goto 1f;" "r0 /= 0;" "1:" "r0 = 42;" "exit;"
:
: __imm(bpf_get_prandom_u32)
: __clobber_all);
}
/* Check that mark_chain_precision() for one of the conditional jump *operandsdoesnottriggerequalscalarsprecisionpropagation.
*/
SEC("socket")
__success __log_level(2)
__msg("3: (25) if r1 > 0x100 goto pc+0")
__msg("frame0: regs=r1 stack= before 2: (bf) r1 = r0")
__naked void cjmp_no_linked_regs_trigger(void)
{ asmvolatile ( /* r0 = random number up to 0xff */ "call %[bpf_ktime_get_ns];" "r0 &= 0xff;" /* tie r0.id == r1.id */ "r1 = r0;" /* the jump below would be predicted, thus r1 would be marked precise, *thisshouldnotimplyprecisionmarkforr0
*/ "if r1 > 256 goto +0;" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
/* Verify that check_ids() is used by regsafe() for scalars. * *r9=...somepointerwithrangeX... *r6=...unboundscalarID=a... *r7=...unboundscalarID=b... *if(r6>r7)goto+1 *r7=r6 *if(r7>X)gotoexit *r9+=r6 *...accessmemoryusingr9... * *Thememoryaccessissafeonlyifr7isbounded, *whichistrueforonebranchandnottrueforanother.
*/
SEC("socket")
__failure __msg("register with unbounded min value")
__flag(BPF_F_TEST_STATE_FREQ)
__naked void check_ids_in_regsafe(void)
{ asmvolatile ( /* Bump allocated stack */ "r1 = 0;" "*(u64*)(r10 - 8) = r1;" /* r9 = pointer to stack */ "r9 = r10;" "r9 += -8;" /* r7 = ktime_get_ns() */ "call %[bpf_ktime_get_ns];" "r7 = r0;" /* r6 = ktime_get_ns() */ "call %[bpf_ktime_get_ns];" "r6 = r0;" /* if r6 > r7 is an unpredictable jump */ "if r6 > r7 goto l1_%=;" "r7 = r6;" "l1_%=:" /* if r7 > 4 ...; transfers range to r6 on one execution path *butdoesnottransferonanother
*/ "if r7 > 4 goto l2_%=;" /* Access memory at r9[r6], r6 is not always bounded */ "r9 += r6;" "r0 = *(u8*)(r9 + 0);" "l2_%=:" "r0 = 0;" "exit;"
:
: __imm(bpf_ktime_get_ns)
: __clobber_all);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.