• Kumar Kartikeya Dwivedi's avatar
    bpf: Allow locking bpf_spin_lock global variables · d0d78c1d
    Kumar Kartikeya Dwivedi authored
    Global variables reside in maps accessible using direct_value_addr
    callbacks, so giving each load instruction's rewrite a unique reg->id
    disallows us from holding locks which are global.
    
    The reason for preserving reg->id as a unique value for registers that
    may point to spin lock is that two separate lookups are treated as two
    separate memory regions, and any possible aliasing is ignored for the
    purposes of spin lock correctness.
    
    This is not great especially for the global variable case, which are
    served from maps that have max_entries == 1, i.e. they always lead to
    map values pointing into the same map value.
    
    So refactor the active_spin_lock into a 'active_lock' structure which
    represents the lock identity, and instead of the reg->id, remember two
    fields, a pointer and the reg->id. The pointer will store reg->map_ptr
    or reg->btf. It's only necessary to distinguish for the id == 0 case of
    global variables, but always setting the pointer to a non-NULL value and
    using the pointer to check whether the lock is held simplifies code in
    the verifier.
    
    This is generic enough to allow it for global variables, map lookups,
    and allocated objects at the same time.
    
    Note that while whether a lock is held can be answered by just comparing
    active_lock.ptr to NULL, to determine whether the register is pointing
    to the same held lock requires comparing _both_ ptr and id.
    
    Finally, as a result of this refactoring, pseudo load instructions are
    not given a unique reg->id, as they are doing lookup for the same map
    value (max_entries is never greater than 1).
    
    Essentially, we consider that the tuple of (ptr, id) will always be
    unique for any kind of argument to bpf_spin_{lock,unlock}.
    
    Note that this can be extended in the future to also remember offset
    used for locking, so that we can introduce multiple bpf_spin_lock fields
    in the same allocation.
    Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
    Link: https://lore.kernel.org/r/20221118015614.2013203-10-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    d0d78c1d
verifier.c 450 KB