• Martin KaFai Lau's avatar
    bpf: Support <8-byte scalar spill and refill · 354e8f19
    Martin KaFai Lau authored
    The verifier currently does not save the reg state when
    spilling <8byte bounded scalar to the stack.  The bpf program
    will be incorrectly rejected when this scalar is refilled to
    the reg and then used to offset into a packet header.
    The later patch has a simplified bpf prog from a real use case
    to demonstrate this case.  The current work around is
    to reparse the packet again such that this offset scalar
    is close to where the packet data will be accessed to
    avoid the spill.  Thus, the header is parsed twice.
    
    The llvm patch [1] will align the <8bytes spill to
    the 8-byte stack address.  This can simplify the verifier
    support by avoiding to store multiple reg states for
    each 8 byte stack slot.
    
    This patch changes the verifier to save the reg state when
    spilling <8bytes scalar to the stack.  This reg state saving
    is limited to spill aligned to the 8-byte stack address.
    The current refill logic has already called coerce_reg_to_size(),
    so coerce_reg_to_size() is not called on state->stack[spi].spilled_ptr
    during spill.
    
    When refilling in check_stack_read_fixed_off(),  it checks
    the refill size is the same as the number of bytes marked with
    STACK_SPILL before restoring the reg state.  When restoring
    the reg state to state->regs[dst_regno], it needs
    to avoid the state->regs[dst_regno].subreg_def being
    over written because it has been marked by the check_reg_arg()
    earlier [check_mem_access() is called after check_reg_arg() in
    do_check()].  Reordering check_mem_access() and check_reg_arg()
    will need a lot of changes in test_verifier's tests because
    of the difference in verifier's error message.  Thus, the
    patch here is to save the state->regs[dst_regno].subreg_def
    first in check_stack_read_fixed_off().
    
    There are cases that the verifier needs to scrub the spilled slot
    from STACK_SPILL to STACK_MISC.  After this patch the spill is not always
    in 8 bytes now, so it can no longer assume the other 7 bytes are always
    marked as STACK_SPILL.  In particular, the scrub needs to avoid marking
    an uninitialized byte from STACK_INVALID to STACK_MISC.  Otherwise, the
    verifier will incorrectly accept bpf program reading uninitialized bytes
    from the stack.  A new helper scrub_spilled_slot() is created for this
    purpose.
    
    [1]: https://reviews.llvm.org/D109073Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Link: https://lore.kernel.org/bpf/20210922004941.625398-1-kafai@fb.com
    354e8f19
verifier.c 396 KB