On Mon, Nov 7, 2022 at 3:10 PM Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> wrote: > > 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 local kptr registers 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: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> > --- > include/linux/bpf_verifier.h | 5 ++++- > kernel/bpf/verifier.c | 41 ++++++++++++++++++++++++------------ > 2 files changed, 32 insertions(+), 14 deletions(-) > > diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h > index 1a32baa78ce2..70cccac62a15 100644 > --- a/include/linux/bpf_verifier.h > +++ b/include/linux/bpf_verifier.h > @@ -323,7 +323,10 @@ struct bpf_verifier_state { > u32 branches; > u32 insn_idx; > u32 curframe; > - u32 active_spin_lock; > + struct { > + void *ptr; document that this could be either struct bpf_map or struct btf pointer, at least? > + u32 id; > + } active_lock; > bool speculative; > > /* first and last insn idx of this verifier state */ [...]