Search code examples
cheaderprototypeebpf

Why load_half is defined in bpf_helpers but it doesn't appear in filter.c?


If I understood "well" within tools/testing/selftests/bpf/bpf_helpers.h bpf heleprs prototypes are defined.

If I want to now which helpers are usable with a specific program type I need to search within the results of 'func_proto(enum bpf_func_id func_id' kernel/ net/ drivers/

For example to check the helpers which a socket filter program can call I can read the following definition

static const struct bpf_func_proto *
sock_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
        switch (func_id) {
        /* inet and inet6 sockets are created in a process
         * context so there is always a valid uid/gid
         */
        case BPF_FUNC_get_current_uid_gid:
                return &bpf_get_current_uid_gid_proto;
        case BPF_FUNC_get_local_storage:
                return &bpf_get_local_storage_proto;
        default:
                return bpf_base_func_proto(func_id);
        }
}

QUESTIONS:

1)I can't see load_half, but still I can call it from my socket filter program. Why? 2) which is the difference between socket_filter and sk_filter?


Solution

    1. load_half() is not a BPF helper. The file bpf_helpers.h that you mentioned does declare the prototypes for the BPF helper functions, but it also contains other useful definitions such as the SEC() or the bpf_printk() macros. In particular, it declares load_half() with the following comment:

      /* llvm builtin functions that eBPF C program may use to
       * emit BPF_LD_ABS and BPF_LD_IND instructions
       */
      [...]
      unsigned long long load_half(void *skb,
                                   unsigned long long off) asm("llvm.bpf.load.half");
      

      As you can read, load_half() is an LLVM builtin, an assembly primitive supported by clang/LLVM which is wrapped as load_half() for convenience. And because it is not a BPF helper, you will not see it when grepping for its prototype in the kernel.

    2. The prefix sk_filter is used for eBPF filters attached to sockets, in a similar fashion as what one can do with the legacy cBPF, to filter incoming packets. Although it may be confusing, you can see that sock_filter_is_valid_access in kernel file net/core/filter.c is used for cg_sock_verifier_ops, which is associated in include/uapi/linux/bpf.h to program type BPF_PROG_TYPE_CGROUP_SOCK_ADDR. So it refers to programs being used in cgroups to help (containerised) applications to bind and connect their sockets correctly.