netfilter: nf_defrag: Skip defrag if NOTRACK is set
authorSubash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Thu, 11 Jan 2018 03:51:57 +0000 (20:51 -0700)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 11 Jan 2018 12:14:20 +0000 (13:14 +0100)
conntrack defrag is needed only if some module like CONNTRACK or NAT
explicitly requests it. For plain forwarding scenarios, defrag is
not needed and can be skipped if NOTRACK is set in a rule.

Since conntrack defrag is currently higher priority than raw table,
setting NOTRACK is not sufficient. We need to move raw to a higher
priority for iptables only.

This is achieved by introducing a module parameter "raw_before_defrag"
which allows to change the priority of raw table to place it before
defrag. By default, the parameter is disabled and the priority of raw
table is NF_IP_PRI_RAW to support legacy behavior. If the module
parameter is enabled, then the priority of the raw table is set to
NF_IP_PRI_RAW_BEFORE_DEFRAG.

Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/uapi/linux/netfilter_ipv4.h
include/uapi/linux/netfilter_ipv6.h
net/ipv4/netfilter/iptable_raw.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv6/netfilter/ip6table_raw.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c

index e6b1a84f5dd31ccd6aceecb1058e76dfa4f3ae0b..c3b060775e130434387895bf14ab8756c36d26d0 100644 (file)
@@ -57,6 +57,7 @@
 
 enum nf_ip_hook_priorities {
        NF_IP_PRI_FIRST = INT_MIN,
+       NF_IP_PRI_RAW_BEFORE_DEFRAG = -450,
        NF_IP_PRI_CONNTRACK_DEFRAG = -400,
        NF_IP_PRI_RAW = -300,
        NF_IP_PRI_SELINUX_FIRST = -225,
index 2f9724611cc245c3e6b57b4051ed550d0c4c6f19..dc624fd24d2546f2bb74f6beea239eee8f3920c1 100644 (file)
@@ -62,6 +62,7 @@
 
 enum nf_ip6_hook_priorities {
        NF_IP6_PRI_FIRST = INT_MIN,
+       NF_IP6_PRI_RAW_BEFORE_DEFRAG = -450,
        NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
        NF_IP6_PRI_RAW = -300,
        NF_IP6_PRI_SELINUX_FIRST = -225,
index a869d1fea7d9bf441b259167191510b553cbe95a..29b64d3024e0ab398b719424e9a278742bf58f47 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/slab.h>
 
 static int __net_init iptable_raw_table_init(struct net *net);
 
-static const struct xt_table packet_raw = {
+static bool raw_before_defrag __read_mostly;
+MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
+module_param(raw_before_defrag, bool, 0000);
+
+static struct xt_table packet_raw = {
        .name = "raw",
        .valid_hooks =  RAW_VALID_HOOKS,
        .me = THIS_MODULE,
@@ -64,6 +69,12 @@ static int __init iptable_raw_init(void)
 {
        int ret;
 
+       if (raw_before_defrag) {
+               packet_raw.priority = NF_IP_PRI_RAW_BEFORE_DEFRAG;
+
+               pr_info("Enabling raw table before defrag\n");
+       }
+
        rawtable_ops = xt_hook_ops_alloc(&packet_raw, iptable_raw_hook);
        if (IS_ERR(rawtable_ops))
                return PTR_ERR(rawtable_ops);
index 37fe1616ca0bcb27ca2a4772dc93851d00b7929a..cbd987f6b1f812223a2bf9709e4c754658052d77 100644 (file)
@@ -80,7 +80,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
 #endif
 #endif
        /* Gather fragments. */
-       if (ip_is_fragment(ip_hdr(skb))) {
+       if (skb->_nfct != IP_CT_UNTRACKED && ip_is_fragment(ip_hdr(skb))) {
                enum ip_defrag_users user =
                        nf_ct_defrag_user(state->hook, skb);
 
index d4bc56443dc17e02a6674b7a90f13b2057ef8558..3df7383f96d073bccfb3e701b8b7ecb3a4973174 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/module.h>
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/slab.h>
 
 static int __net_init ip6table_raw_table_init(struct net *net);
 
-static const struct xt_table packet_raw = {
+static bool raw_before_defrag __read_mostly;
+MODULE_PARM_DESC(raw_before_defrag, "Enable raw table before defrag");
+module_param(raw_before_defrag, bool, 0000);
+
+static struct xt_table packet_raw = {
        .name = "raw",
        .valid_hooks = RAW_VALID_HOOKS,
        .me = THIS_MODULE,
@@ -63,6 +68,12 @@ static int __init ip6table_raw_init(void)
 {
        int ret;
 
+       if (raw_before_defrag) {
+               packet_raw.priority = NF_IP6_PRI_RAW_BEFORE_DEFRAG;
+
+               pr_info("Enabling raw table before defrag\n");
+       }
+
        /* Register hooks */
        rawtable_ops = xt_hook_ops_alloc(&packet_raw, ip6table_raw_hook);
        if (IS_ERR(rawtable_ops))
index b326da59257f60396cda3daddfd643a3cec262a5..87b503a8f5efe63131b24e2642dd743d433b038c 100644 (file)
@@ -65,6 +65,9 @@ static unsigned int ipv6_defrag(void *priv,
                return NF_ACCEPT;
 #endif
 
+       if (skb->_nfct == IP_CT_UNTRACKED)
+               return NF_ACCEPT;
+
        err = nf_ct_frag6_gather(state->net, skb,
                                 nf_ct6_defrag_user(state->hook, skb));
        /* queued */