Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

filter: add ANC_PAY_OFFSET instruction for loading payload start offset

It is very useful to do dynamic truncation of packets. In particular,
we're interested to push the necessary header bytes to the user space and
cut off user payload that should probably not be transferred for some reasons
(e.g. privacy, speed, or others). With the ancillary extension PAY_OFFSET,
we can load it into the accumulator, and return it. E.g. in bpfc syntax ...

ld #poff ; { 0x20, 0, 0, 0xfffff034 },
ret a ; { 0x16, 0, 0, 0x00000000 },

... as a filter will accomplish this without having to do a big hackery in
a BPF filter itself. Follow-up JIT implementations are welcome.

Thanks to Eric Dumazet for suggesting and discussing this during the
Netfilter Workshop in Copenhagen.

Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Daniel Borkmann and committed by
David S. Miller
3e5289d5 f77668dc

+8 -1
+1
include/linux/filter.h
··· 126 126 BPF_S_ANC_SECCOMP_LD_W, 127 127 BPF_S_ANC_VLAN_TAG, 128 128 BPF_S_ANC_VLAN_TAG_PRESENT, 129 + BPF_S_ANC_PAY_OFFSET, 129 130 }; 130 131 131 132 #endif /* __LINUX_FILTER_H__ */
+2 -1
include/uapi/linux/filter.h
··· 129 129 #define SKF_AD_ALU_XOR_X 40 130 130 #define SKF_AD_VLAN_TAG 44 131 131 #define SKF_AD_VLAN_TAG_PRESENT 48 132 - #define SKF_AD_MAX 52 132 + #define SKF_AD_PAY_OFFSET 52 133 + #define SKF_AD_MAX 56 133 134 #define SKF_NET_OFF (-0x100000) 134 135 #define SKF_LL_OFF (-0x200000) 135 136
+5
net/core/filter.c
··· 348 348 case BPF_S_ANC_VLAN_TAG_PRESENT: 349 349 A = !!vlan_tx_tag_present(skb); 350 350 continue; 351 + case BPF_S_ANC_PAY_OFFSET: 352 + A = __skb_get_poff(skb); 353 + continue; 351 354 case BPF_S_ANC_NLATTR: { 352 355 struct nlattr *nla; 353 356 ··· 615 612 ANCILLARY(ALU_XOR_X); 616 613 ANCILLARY(VLAN_TAG); 617 614 ANCILLARY(VLAN_TAG_PRESENT); 615 + ANCILLARY(PAY_OFFSET); 618 616 } 619 617 620 618 /* ancillary operation unknown or unsupported */ ··· 818 814 [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS, 819 815 [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, 820 816 [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, 817 + [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, 821 818 [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN, 822 819 [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND, 823 820 [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND,