-->

BPF: translation of program contexts

2019-05-28 19:35发布

问题:

I was looking at the different types of BPF program, and noticed that for different program types the context is being passed differently.

Example:

  1. For program type BPF_PROG_TYPE_SOCK_OPS, an object of type struct bpf_sock_ops_kern is passed. However, the BPF program of this type takes a reference to struct bpf_sock_ops. Why is it done this way and where is the "translation" from bpf_sock_ops_kern to bpf_sock_ops?

  2. For program type BPF_PROG_TYPE_CGROUP_SKB, an object of type struct sk_buff is passed (e.g., in __cgroup_bpf_run_filter_skb), but the BPF program expects a minimized version, struct __sk_buff.

So I looked at the struct bpf_verifier_ops function callbacks, but they seem to only adjust the offsets in BPF instructions, as they are called by the BPF verifier.

I'd be glad if someone could shed light on how the BPF context is defined. Thanks.

回答1:

The mirror objects (e.g., struct bpf_sock_ops) passed as argument expose a subset of the original object(s)'s fields to the BPF program. The mirror structure can also have fields from several different original structures; in that case, the mirror object serves as aggregate. Passing the original object(s) to the BPF program would also be misleading as the user could think they have access to all fields. For example, they could think they have access to bpf_sock_ops_kern.sk when that's actually not the case.

The verifier then converts accesses to the mirror object into accesses to the original object(s), before the program is executed for the first time. There's a conversion function for each type of mirror object (e.g., sock_ops_convert_ctx_access for the conversion of accesses to struct bpf_sock_ops). Then, for each field of the mirror object (i.e., for each offset), the conversion function rewrites the load or store instruction with the offset to the original field.

Note that all original fields might not be in the same object. For example, in the mirror object struct bpf_sock_ops, the fields op and family are retrieved in bpf_sock_ops_kern.op and bpf_sock_ops_kern.sk->skc_family respectively.