• Paul Chaignon's avatar
    bpf: mark registers in all frames after pkt/null checks · c6a9efa1
    Paul Chaignon authored
    In case of a null check on a pointer inside a subprog, we should mark all
    registers with this pointer as either safe or unknown, in both the current
    and previous frames.  Currently, only spilled registers and registers in
    the current frame are marked.  Packet bound checks in subprogs have the
    same issue.  This patch fixes it to mark registers in previous frames as
    well.
    
    A good reproducer for null checks looks as follow:
    
    1: ptr = bpf_map_lookup_elem(map, &key);
    2: ret = subprog(ptr) {
    3:   return ptr != NULL;
    4: }
    5: if (ret)
    6:   value = *ptr;
    
    With the above, the verifier will complain on line 6 because it sees ptr
    as map_value_or_null despite the null check in subprog 1.
    
    Note that this patch fixes another resulting bug when using
    bpf_sk_release():
    
    1: sk = bpf_sk_lookup_tcp(...);
    2: subprog(sk) {
    3:   if (sk)
    4:     bpf_sk_release(sk);
    5: }
    6: if (!sk)
    7:   return 0;
    8: return 1;
    
    In the above, mark_ptr_or_null_regs will warn on line 6 because it will
    try to free the reference state, even though it was already freed on
    line 3.
    
    Fixes: f4d7e40a ("bpf: introduce function calls (verification)")
    Signed-off-by: default avatarPaul Chaignon <paul.chaignon@orange.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    c6a9efa1
verifier.c 229 KB