• Jakub Kicinski's avatar
    bpf: fix method of PTR_TO_PACKET reg id generation · d8e294b0
    Jakub Kicinski authored
    [ Upstream commit 1f415a74 ]
    
    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: 969bf05e ("bpf: direct packet access")
    Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
    Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Acked-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    d8e294b0
verifier.c 76.5 KB