• Martin KaFai Lau's avatar
    bpf: Enable bpf_skc_to_* sock casting helper to networking prog type · 1df8f55a
    Martin KaFai Lau authored
    There is a constant need to add more fields into the bpf_tcp_sock
    for the bpf programs running at tc, sock_ops...etc.
    
    A current workaround could be to use bpf_probe_read_kernel().  However,
    other than making another helper call for reading each field and missing
    CO-RE, it is also not as intuitive to use as directly reading
    "tp->lsndtime" for example.  While already having perfmon cap to do
    bpf_probe_read_kernel(), it will be much easier if the bpf prog can
    directly read from the tcp_sock.
    
    This patch tries to do that by using the existing casting-helpers
    bpf_skc_to_*() whose func_proto returns a btf_id.  For example, the
    func_proto of bpf_skc_to_tcp_sock returns the btf_id of the
    kernel "struct tcp_sock".
    
    These helpers are also added to is_ptr_cast_function().
    It ensures the returning reg (BPF_REF_0) will also carries the ref_obj_id.
    That will keep the ref-tracking works properly.
    
    The bpf_skc_to_* helpers are made available to most of the bpf prog
    types in filter.c. The bpf_skc_to_* helpers will be limited by
    perfmon cap.
    
    This patch adds a ARG_PTR_TO_BTF_ID_SOCK_COMMON.  The helper accepting
    this arg can accept a btf-id-ptr (PTR_TO_BTF_ID + &btf_sock_ids[BTF_SOCK_TYPE_SOCK_COMMON])
    or a legacy-ctx-convert-skc-ptr (PTR_TO_SOCK_COMMON).  The bpf_skc_to_*()
    helpers are changed to take ARG_PTR_TO_BTF_ID_SOCK_COMMON such that
    they will accept pointer obtained from skb->sk.
    
    Instead of specifying both arg_type and arg_btf_id in the same func_proto
    which is how the current ARG_PTR_TO_BTF_ID does, the arg_btf_id of
    the new ARG_PTR_TO_BTF_ID_SOCK_COMMON is specified in the
    compatible_reg_types[] in verifier.c.  The reason is the arg_btf_id is
    always the same.  Discussion in this thread:
    https://lore.kernel.org/bpf/20200922070422.1917351-1-kafai@fb.com/
    
    The ARG_PTR_TO_BTF_ID_ part gives a clear expectation that the helper is
    expecting a PTR_TO_BTF_ID which could be NULL.  This is the same
    behavior as the existing helper taking ARG_PTR_TO_BTF_ID.
    
    The _SOCK_COMMON part means the helper is also expecting the legacy
    SOCK_COMMON pointer.
    
    By excluding the _OR_NULL part, the bpf prog cannot call helper
    with a literal NULL which doesn't make sense in most cases.
    e.g. bpf_skc_to_tcp_sock(NULL) will be rejected.  All PTR_TO_*_OR_NULL
    reg has to do a NULL check first before passing into the helper or else
    the bpf prog will be rejected.  This behavior is nothing new and
    consistent with the current expectation during bpf-prog-load.
    
    [ ARG_PTR_TO_BTF_ID_SOCK_COMMON will be used to replace
      ARG_PTR_TO_SOCK* of other existing helpers later such that
      those existing helpers can take the PTR_TO_BTF_ID returned by
      the bpf_skc_to_*() helpers.
    
      The only special case is bpf_sk_lookup_assign() which can accept a
      literal NULL ptr.  It has to be handled specially in another follow
      up patch if there is a need (e.g. by renaming ARG_PTR_TO_SOCKET_OR_NULL
      to ARG_PTR_TO_BTF_ID_SOCK_COMMON_OR_NULL). ]
    
    [ When converting the older helpers that take ARG_PTR_TO_SOCK* in
      the later patch, if the kernel does not support BTF,
      ARG_PTR_TO_BTF_ID_SOCK_COMMON will behave like ARG_PTR_TO_SOCK_COMMON
      because no reg->type could have PTR_TO_BTF_ID in this case.
    
      It is not a concern for the newer-btf-only helper like the bpf_skc_to_*()
      here though because these helpers must require BTF vmlinux to begin
      with. ]
    Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
    Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
    Link: https://lore.kernel.org/bpf/20200925000350.3855720-1-kafai@fb.com
    1df8f55a
filter.c 268 KB