• Andrii Nakryiko's avatar
    bpf: enforce types for __arg_ctx-tagged arguments in global subprogs · 0ba97151
    Andrii Nakryiko authored
    Add enforcement of expected types for context arguments tagged with
    arg:ctx (__arg_ctx) tag.
    
    First, any program type will accept generic `void *` context type when
    combined with __arg_ctx tag.
    
    Besides accepting "canonical" struct names and `void *`, for a bunch of
    program types for which program context is actually a named struct, we
    allows a bunch of pragmatic exceptions to match real-world and expected
    usage:
    
      - for both kprobes and perf_event we allow `bpf_user_pt_regs_t *` as
        canonical context argument type, where `bpf_user_pt_regs_t` is a
        *typedef*, not a struct;
      - for kprobes, we also always accept `struct pt_regs *`, as that's what
        actually is passed as a context to any kprobe program;
      - for perf_event, we resolve typedefs (unless it's `bpf_user_pt_regs_t`)
        down to actual struct type and accept `struct pt_regs *`, or
        `struct user_pt_regs *`, or `struct user_regs_struct *`, depending
        on the actual struct type kernel architecture points `bpf_user_pt_regs_t`
        typedef to; otherwise, canonical `struct bpf_perf_event_data *` is
        expected;
      - for raw_tp/raw_tp.w programs, `u64/long *` are accepted, as that's
        what's expected with BPF_PROG() usage; otherwise, canonical
        `struct bpf_raw_tracepoint_args *` is expected;
      - tp_btf supports both `struct bpf_raw_tracepoint_args *` and `u64 *`
        formats, both are coded as expections as tp_btf is actually a TRACING
        program type, which has no canonical context type;
      - iterator programs accept `struct bpf_iter__xxx *` structs, currently
        with no further iterator-type specific enforcement;
      - fentry/fexit/fmod_ret/lsm/struct_ops all accept `u64 *`;
      - classic tracepoint programs, as well as syscall and freplace
        programs allow any user-provided type.
    
    In all other cases kernel will enforce exact match of struct name to
    expected canonical type. And if user-provided type doesn't match that
    expectation, verifier will emit helpful message with expected type name.
    
    Note a bit unnatural way the check is done after processing all the
    arguments. This is done to avoid conflict between bpf and bpf-next
    trees. Once trees converge, a small follow up patch will place a simple
    btf_validate_prog_ctx_type() check into a proper ARG_PTR_TO_CTX branch
    (which bpf-next tree patch refactored already), removing duplicated
    arg:ctx detection logic.
    Suggested-by: default avatarAlexei Starovoitov <ast@kernel.org>
    Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
    Link: https://lore.kernel.org/r/20240118033143.3384355-4-andrii@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    0ba97151
btf.c 222 KB