2017-05-13 23:36 GMT+02:00 David Miller <davem@xxxxxxxxxxxxx>: <snip> > So our example program above needs a little bit of an adjustment to > make it suitable for BPF_PROG_TYPE_SOCK_FILTER: > > SEC("my_program") > int my_main(struct __sk_buff *skb) > { > void *data_end = (void *)(long)skb->data_end; > void *data = (void *)(long)skb->data; > struct ethhdr *eth = (struct ethhdr *)(data); > int len = skb->len; > > if (eth + 1 > data_end) > return 0; > if (eth->h_proto == bpf_htons(ETH_P_IP)) > return len; > return 0; > } > > So what changed is that we load "len" from the context metadata and > return "len" when we want to accept the packet. This says "accept > the packet and do not truncate it." This cannot work with BPF_PROG_TYPE_SOCKET_FILTER because skb->data_end and skb->data cannot be accessed by this BPF_PROG type. The verifier will reject it with 0: (b7) r0 = 0 1: (61) r2 = *(u32 *)(r1 +80) invalid bpf_context access off=80 size=4 Reason for that is the function sk_filter_is_valid_access which checks the access to the __sk_buff context pointer (r1): static bool sk_filter_is_valid_access(int off, int size, enum bpf_access_type type, struct bpf_insn_access_aux *info) { switch (off) { case bpf_ctx_range(struct __sk_buff, tc_classid): case bpf_ctx_range(struct __sk_buff, data): case bpf_ctx_range(struct __sk_buff, data_meta): case bpf_ctx_range(struct __sk_buff, data_end): case bpf_ctx_range_till(struct __sk_buff, family, local_port): return false; }