• Yonghong Song's avatar
    bpf: Avoid verifier failure for 32bit pointer arithmetic · 6c693541
    Yonghong Song authored
    When do experiments with llvm (disabling instcombine and
    simplifyCFG), I hit the following error with test_seg6_loop.o.
    
      ; R1=pkt(id=0,off=0,r=48,imm=0), R7=pkt(id=0,off=40,r=48,imm=0)
      w2 = w7
      ; R2_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff))
      w2 -= w1
      R2 32-bit pointer arithmetic prohibited
    
    The corresponding source code is:
      uint32_t srh_off
      // srh and skb->data are all packet pointers
      srh_off = (char *)srh - (char *)(long)skb->data;
    
    The verifier does not support 32-bit pointer/scalar arithmetic.
    
    Without my llvm change, the code looks like
    
      ; R3=pkt(id=0,off=40,r=48,imm=0), R8=pkt(id=0,off=0,r=48,imm=0)
      w3 -= w8
      ; R3_w=inv(id=0)
    
    This is explicitly allowed in verifier if both registers are
    pointers and the opcode is BPF_SUB.
    
    To fix this problem, I changed the verifier to allow
    32-bit pointer/scaler BPF_SUB operations.
    
    At the source level, the issue could be workarounded with
    inline asm or changing "uint32_t srh_off" to "uint64_t srh_off".
    But I feel that verifier change might be the right thing to do.
    Signed-off-by: default avatarYonghong Song <yhs@fb.com>
    Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
    Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
    Link: https://lore.kernel.org/bpf/20200618234631.3321118-1-yhs@fb.com
    6c693541
verifier.c 318 KB