On Tue, Aug 02, 2016 at 04:12:14PM +0100, Jakub Kicinski wrote:
> Using per-register incrementing ID can lead to
> find_good_pkt_pointers() confusing registers which
> have completely different values.  Consider example:
> 
> 0: (bf) r6 = r1
> 1: (61) r8 = *(u32 *)(r6 +76)
> 2: (61) r0 = *(u32 *)(r6 +80)
> 3: (bf) r7 = r8
> 4: (07) r8 += 32
> 5: (2d) if r8 > r0 goto pc+9
>  R0=pkt_end R1=ctx R6=ctx R7=pkt(id=0,off=0,r=32) R8=pkt(id=0,off=32,r=32) 
> R10=fp
> 6: (bf) r8 = r7
> 7: (bf) r9 = r7
> 8: (71) r1 = *(u8 *)(r7 +0)
> 9: (0f) r8 += r1
> 10: (71) r1 = *(u8 *)(r7 +1)
> 11: (0f) r9 += r1
> 12: (07) r8 += 32
> 13: (2d) if r8 > r0 goto pc+1
>  R0=pkt_end R1=inv56 R6=ctx R7=pkt(id=0,off=0,r=32) R8=pkt(id=1,off=32,r=32) 
> R9=pkt(id=1,off=0,r=32) R10=fp
> 14: (71) r1 = *(u8 *)(r9 +16)
> 15: (b7) r7 = 0
> 16: (bf) r0 = r7
> 17: (95) exit
> 
> We need to get a UNKNOWN_VALUE with imm to force id
> generation so lines 0-5 make r7 a valid packet pointer.
> We then read two different bytes from the packet and
> add them to copies of the constructed packet pointer.
> r8 (line 9) and r9 (line 11) will get the same id of 1,
> independently.  When either of them is validated (line
> 13) - find_good_pkt_pointers() will also mark the other
> as safe.  This leads to access on line 14 being mistakenly
> considered safe.
> 
> Fixes: 969bf05eb3ce ("bpf: direct packet access")
> Signed-off-by: Jakub Kicinski <jakub.kicin...@netronome.com>

Great catch. Thanks!
Acked-by: Alexei Starovoitov <a...@kernel.org>

Reply via email to