• Kumar Kartikeya Dwivedi's avatar
    bpf: Add reference tracking support to kfunc · 5c073f26
    Kumar Kartikeya Dwivedi authored
    This patch adds verifier support for PTR_TO_BTF_ID return type of kfunc
    to be a reference, by reusing acquire_reference_state/release_reference
    support for existing in-kernel bpf helpers.
    
    We make use of the three kfunc types:
    
    - BTF_KFUNC_TYPE_ACQUIRE
      Return true if kfunc_btf_id is an acquire kfunc.  This will
      acquire_reference_state for the returned PTR_TO_BTF_ID (this is the
      only allow return value). Note that acquire kfunc must always return a
      PTR_TO_BTF_ID{_OR_NULL}, otherwise the program is rejected.
    
    - BTF_KFUNC_TYPE_RELEASE
      Return true if kfunc_btf_id is a release kfunc.  This will release the
      reference to the passed in PTR_TO_BTF_ID which has a reference state
      (from earlier acquire kfunc).
      The btf_check_func_arg_match returns the regno (of argument register,
      hence > 0) if the kfunc is a release kfunc, and a proper referenced
      PTR_TO_BTF_ID is being passed to it.
      This is similar to how helper call check uses bpf_call_arg_meta to
      store the ref_obj_id that is later used to release the reference.
      Similar to in-kernel helper, we only allow passing one referenced
      PTR_TO_BTF_ID as an argument. It can also be passed in to normal
      kfunc, but in case of release kfunc there must always be one
      PTR_TO_BTF_ID argument that is referenced.
    
    - BTF_KFUNC_TYPE_RET_NULL
      For kfunc returning PTR_TO_BTF_ID, tells if it can be NULL, hence
      force caller to mark the pointer not null (using check) before
      accessing it. Note that taking into account the case fixed by commit
      93c230e3 ("bpf: Enforce id generation for all may-be-null register type")
      we assign a non-zero id for mark_ptr_or_null_reg logic. Later, if more
      return types are supported by kfunc, which have a _OR_NULL variant, it
      might be better to move this id generation under a common
      reg_type_may_be_null check, similar to the case in the commit.
    
    Referenced PTR_TO_BTF_ID is currently only limited to kfunc, but can be
    extended in the future to other BPF helpers as well.  For now, we can
    rely on the btf_struct_ids_match check to ensure we get the pointer to
    the expected struct type. In the future, care needs to be taken to avoid
    ambiguity for reference PTR_TO_BTF_ID passed to release function, in
    case multiple candidates can release same BTF ID.
    
    e.g. there might be two release kfuncs (or kfunc and helper):
    
    foo(struct abc *p);
    bar(struct abc *p);
    
    ... such that both release a PTR_TO_BTF_ID with btf_id of struct abc. In
    this case we would need to track the acquire function corresponding to
    the release function to avoid type confusion, and store this information
    in the register state so that an incorrect program can be rejected. This
    is not a problem right now, hence it is left as an exercise for the
    future patch introducing such a case in the kernel.
    Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
    Link: https://lore.kernel.org/r/20220114163953.1455836-6-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    5c073f26
btf.c 183 KB