Commit 3e5289d5 authored by Daniel Borkmann's avatar Daniel Borkmann Committed by David S. Miller

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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f77668dc
...@@ -126,6 +126,7 @@ enum { ...@@ -126,6 +126,7 @@ enum {
BPF_S_ANC_SECCOMP_LD_W, BPF_S_ANC_SECCOMP_LD_W,
BPF_S_ANC_VLAN_TAG, BPF_S_ANC_VLAN_TAG,
BPF_S_ANC_VLAN_TAG_PRESENT, BPF_S_ANC_VLAN_TAG_PRESENT,
BPF_S_ANC_PAY_OFFSET,
}; };
#endif /* __LINUX_FILTER_H__ */ #endif /* __LINUX_FILTER_H__ */
...@@ -129,7 +129,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */ ...@@ -129,7 +129,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
#define SKF_AD_ALU_XOR_X 40 #define SKF_AD_ALU_XOR_X 40
#define SKF_AD_VLAN_TAG 44 #define SKF_AD_VLAN_TAG 44
#define SKF_AD_VLAN_TAG_PRESENT 48 #define SKF_AD_VLAN_TAG_PRESENT 48
#define SKF_AD_MAX 52 #define SKF_AD_PAY_OFFSET 52
#define SKF_AD_MAX 56
#define SKF_NET_OFF (-0x100000) #define SKF_NET_OFF (-0x100000)
#define SKF_LL_OFF (-0x200000) #define SKF_LL_OFF (-0x200000)
......
...@@ -348,6 +348,9 @@ unsigned int sk_run_filter(const struct sk_buff *skb, ...@@ -348,6 +348,9 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
case BPF_S_ANC_VLAN_TAG_PRESENT: case BPF_S_ANC_VLAN_TAG_PRESENT:
A = !!vlan_tx_tag_present(skb); A = !!vlan_tx_tag_present(skb);
continue; continue;
case BPF_S_ANC_PAY_OFFSET:
A = __skb_get_poff(skb);
continue;
case BPF_S_ANC_NLATTR: { case BPF_S_ANC_NLATTR: {
struct nlattr *nla; struct nlattr *nla;
...@@ -612,6 +615,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) ...@@ -612,6 +615,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
ANCILLARY(ALU_XOR_X); ANCILLARY(ALU_XOR_X);
ANCILLARY(VLAN_TAG); ANCILLARY(VLAN_TAG);
ANCILLARY(VLAN_TAG_PRESENT); ANCILLARY(VLAN_TAG_PRESENT);
ANCILLARY(PAY_OFFSET);
} }
/* ancillary operation unknown or unsupported */ /* ancillary operation unknown or unsupported */
...@@ -814,6 +818,7 @@ static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) ...@@ -814,6 +818,7 @@ static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
[BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS, [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS,
[BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN, [BPF_S_LD_W_LEN] = BPF_LD|BPF_W|BPF_LEN,
[BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND, [BPF_S_LD_W_IND] = BPF_LD|BPF_W|BPF_IND,
[BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND, [BPF_S_LD_H_IND] = BPF_LD|BPF_H|BPF_IND,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment