• Andrey Ignatov's avatar
    bpf: Allow narrow loads with offset > 0 · 46f53a65
    Andrey Ignatov authored
    Currently BPF verifier allows narrow loads for a context field only with
    offset zero. E.g. if there is a __u32 field then only the following
    loads are permitted:
      * off=0, size=1 (narrow);
      * off=0, size=2 (narrow);
      * off=0, size=4 (full).
    
    On the other hand LLVM can generate a load with offset different than
    zero that make sense from program logic point of view, but verifier
    doesn't accept it.
    
    E.g. tools/testing/selftests/bpf/sendmsg4_prog.c has code:
    
      #define DST_IP4			0xC0A801FEU /* 192.168.1.254 */
      ...
      	if ((ctx->user_ip4 >> 24) == (bpf_htonl(DST_IP4) >> 24) &&
    
    where ctx is struct bpf_sock_addr.
    
    Some versions of LLVM can produce the following byte code for it:
    
           8:       71 12 07 00 00 00 00 00         r2 = *(u8 *)(r1 + 7)
           9:       67 02 00 00 18 00 00 00         r2 <<= 24
          10:       18 03 00 00 00 00 00 fe 00 00 00 00 00 00 00 00         r3 = 4261412864 ll
          12:       5d 32 07 00 00 00 00 00         if r2 != r3 goto +7 <LBB0_6>
    
    where `*(u8 *)(r1 + 7)` means narrow load for ctx->user_ip4 with size=1
    and offset=3 (7 - sizeof(ctx->user_family) = 3). This load is currently
    rejected by verifier.
    
    Verifier code that rejects such loads is in bpf_ctx_narrow_access_ok()
    what means any is_valid_access implementation, that uses the function,
    works this way, e.g. bpf_skb_is_valid_access() for __sk_buff or
    sock_addr_is_valid_access() for bpf_sock_addr.
    
    The patch makes such loads supported. Offset can be in [0; size_default)
    but has to be multiple of load size. E.g. for __u32 field the following
    loads are supported now:
      * off=0, size=1 (narrow);
      * off=1, size=1 (narrow);
      * off=2, size=1 (narrow);
      * off=3, size=1 (narrow);
      * off=0, size=2 (narrow);
      * off=2, size=2 (narrow);
      * off=0, size=4 (full).
    Reported-by: default avatarYonghong Song <yhs@fb.com>
    Signed-off-by: default avatarAndrey Ignatov <rdna@fb.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    46f53a65
verifier.c 188 KB