filter: add ANC_PAY_OFFSET instruction for loading payload start offset
authorDaniel Borkmann <dborkman@redhat.com>
Tue, 19 Mar 2013 06:39:31 +0000 (06:39 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 20 Mar 2013 17:15:45 +0000 (13:15 -0400)
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>
include/linux/filter.h
include/uapi/linux/filter.h
net/core/filter.c

index c45eabc135e1f00b7825d017b37df1666acb203e..d2059cb4e465090dec64feb502f0fa2a17ec2cb9 100644 (file)
@@ -126,6 +126,7 @@ enum {
        BPF_S_ANC_SECCOMP_LD_W,
        BPF_S_ANC_VLAN_TAG,
        BPF_S_ANC_VLAN_TAG_PRESENT,
+       BPF_S_ANC_PAY_OFFSET,
 };
 
 #endif /* __LINUX_FILTER_H__ */
index 9cfde6941099635ee567d28e240f8cbc02386f51..8eb9ccaa5b48124b716e5abe7741aef4ca711d9f 100644 (file)
@@ -129,7 +129,8 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
 #define SKF_AD_ALU_XOR_X       40
 #define SKF_AD_VLAN_TAG        44
 #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_LL_OFF    (-0x200000)
 
index 2e20b55a7830c43e25bdd4221cc134f374d7148e..dad2a178f9f8a477488f091962c5e771d1d117b3 100644 (file)
@@ -348,6 +348,9 @@ load_b:
                case BPF_S_ANC_VLAN_TAG_PRESENT:
                        A = !!vlan_tx_tag_present(skb);
                        continue;
+               case BPF_S_ANC_PAY_OFFSET:
+                       A = __skb_get_poff(skb);
+                       continue;
                case BPF_S_ANC_NLATTR: {
                        struct nlattr *nla;
 
@@ -612,6 +615,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
                        ANCILLARY(ALU_XOR_X);
                        ANCILLARY(VLAN_TAG);
                        ANCILLARY(VLAN_TAG_PRESENT);
+                       ANCILLARY(PAY_OFFSET);
                        }
 
                        /* ancillary operation unknown or unsupported */
@@ -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_VLAN_TAG]    = 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_IND]        = BPF_LD|BPF_W|BPF_IND,
                [BPF_S_LD_H_IND]        = BPF_LD|BPF_H|BPF_IND,