• Andrey Ignatov's avatar
    bpf: Sanity check max value for var_off stack access · 107c26a7
    Andrey Ignatov authored
    As discussed in [1] max value of variable offset has to be checked for
    overflow on stack access otherwise verifier would accept code like this:
    
      0: (b7) r2 = 6
      1: (b7) r3 = 28
      2: (7a) *(u64 *)(r10 -16) = 0
      3: (7a) *(u64 *)(r10 -8) = 0
      4: (79) r4 = *(u64 *)(r1 +168)
      5: (c5) if r4 s< 0x0 goto pc+4
       R1=ctx(id=0,off=0,imm=0) R2=inv6 R3=inv28
       R4=inv(id=0,umax_value=9223372036854775807,var_off=(0x0;
       0x7fffffffffffffff)) R10=fp0,call_-1 fp-8=mmmmmmmm fp-16=mmmmmmmm
      6: (17) r4 -= 16
      7: (0f) r4 += r10
      8: (b7) r5 = 8
      9: (85) call bpf_getsockopt#57
      10: (b7) r0 = 0
      11: (95) exit
    
    , where R4 obviosly has unbounded max value.
    
    Fix it by checking that reg->smax_value is inside (-BPF_MAX_VAR_OFF;
    BPF_MAX_VAR_OFF) range.
    
    reg->smax_value is used instead of reg->umax_value because stack
    pointers are calculated using negative offset from fp. This is opposite
    to e.g. map access where offset must be non-negative and where
    umax_value is used.
    
    Also dedicated verbose logs are added for both min and max bound check
    failures to have diagnostics consistent with variable offset handling in
    check_map_access().
    
    [1] https://marc.info/?l=linux-netdev&m=155433357510597&w=2
    
    Fixes: 2011fccf ("bpf: Support variable offset stack access from helpers")
    Reported-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: default avatarAndrey Ignatov <rdna@fb.com>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    107c26a7
verifier.c 233 KB