• Dave Marchevsky's avatar
    bpf: Add bpf_refcount_acquire kfunc · 7c50b1cb
    Dave Marchevsky authored
    Currently, BPF programs can interact with the lifetime of refcounted
    local kptrs in the following ways:
    
      bpf_obj_new  - Initialize refcount to 1 as part of new object creation
      bpf_obj_drop - Decrement refcount and free object if it's 0
      collection add - Pass ownership to the collection. No change to
                       refcount but collection is responsible for
    		   bpf_obj_dropping it
    
    In order to be able to add a refcounted local kptr to multiple
    collections we need to be able to increment the refcount and acquire a
    new owning reference. This patch adds a kfunc, bpf_refcount_acquire,
    implementing such an operation.
    
    bpf_refcount_acquire takes a refcounted local kptr and returns a new
    owning reference to the same underlying memory as the input. The input
    can be either owning or non-owning. To reinforce why this is safe,
    consider the following code snippets:
    
      struct node *n = bpf_obj_new(typeof(*n)); // A
      struct node *m = bpf_refcount_acquire(n); // B
    
    In the above snippet, n will be alive with refcount=1 after (A), and
    since nothing changes that state before (B), it's obviously safe. If
    n is instead added to some rbtree, we can still safely refcount_acquire
    it:
    
      struct node *n = bpf_obj_new(typeof(*n));
      struct node *m;
    
      bpf_spin_lock(&glock);
      bpf_rbtree_add(&groot, &n->node, less);   // A
      m = bpf_refcount_acquire(n);              // B
      bpf_spin_unlock(&glock);
    
    In the above snippet, after (A) n is a non-owning reference, and after
    (B) m is an owning reference pointing to the same memory as n. Although
    n has no ownership of that memory's lifetime, it's guaranteed to be
    alive until the end of the critical section, and n would be clobbered if
    we were past the end of the critical section, so it's safe to bump
    refcount.
    
    Implementation details:
    
    * From verifier's perspective, bpf_refcount_acquire handling is similar
      to bpf_obj_new and bpf_obj_drop. Like the former, it returns a new
      owning reference matching input type, although like the latter, type
      can be inferred from concrete kptr input. Verifier changes in
      {check,fixup}_kfunc_call and check_kfunc_args are largely copied from
      aforementioned functions' verifier changes.
    
    * An exception to the above is the new KF_ARG_PTR_TO_REFCOUNTED_KPTR
      arg, indicated by new "__refcounted_kptr" kfunc arg suffix. This is
      necessary in order to handle both owning and non-owning input without
      adding special-casing to "__alloc" arg handling. Also a convenient
      place to confirm that input type has bpf_refcount field.
    
    * The implemented kfunc is actually bpf_refcount_acquire_impl, with
      'hidden' second arg that the verifier sets to the type's struct_meta
      in fixup_kfunc_call.
    Signed-off-by: default avatarDave Marchevsky <davemarchevsky@fb.com>
    Link: https://lore.kernel.org/r/20230415201811.343116-5-davemarchevsky@fb.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    7c50b1cb
bpf_experimental.h 3.43 KB