netfilter: conntrack: avoid zeroing timer
authorFlorian Westphal <fw@strlen.de>
Mon, 24 Nov 2014 14:25:57 +0000 (15:25 +0100)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 27 Nov 2014 11:41:06 +0000 (12:41 +0100)
add a __nfct_init_offset annotation member to struct nf_conn to make
it clear which members are covered by the memset when the conntrack
is allocated.

This avoids zeroing timer_list and ct_net; both are already inited
explicitly.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_conntrack.h
net/netfilter/nf_conntrack_core.c

index c8a7db6..f0daed2 100644 (file)
@@ -92,12 +92,18 @@ struct nf_conn {
        /* Have we seen traffic both ways yet? (bitset) */
        unsigned long status;
 
-       /* If we were expected by an expectation, this will be it */
-       struct nf_conn *master;
-
        /* Timer function; drops refcnt when it goes off. */
        struct timer_list timeout;
 
+#ifdef CONFIG_NET_NS
+       struct net *ct_net;
+#endif
+       /* all members below initialized via memset */
+       u8 __nfct_init_offset[0];
+
+       /* If we were expected by an expectation, this will be it */
+       struct nf_conn *master;
+
 #if defined(CONFIG_NF_CONNTRACK_MARK)
        u_int32_t mark;
 #endif
@@ -108,9 +114,6 @@ struct nf_conn {
 
        /* Extensions */
        struct nf_ct_ext *ext;
-#ifdef CONFIG_NET_NS
-       struct net *ct_net;
-#endif
 
        /* Storage reserved for other modules, must be the last member */
        union nf_conntrack_proto proto;
index 2c69975..9ef88c8 100644 (file)
@@ -826,22 +826,19 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
                atomic_dec(&net->ct.count);
                return ERR_PTR(-ENOMEM);
        }
-       /*
-        * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next
-        * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged.
-        */
-       memset(&ct->tuplehash[IP_CT_DIR_MAX], 0,
-              offsetof(struct nf_conn, proto) -
-              offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX]));
        spin_lock_init(&ct->lock);
        ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
        ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
        ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl;
        /* save hash for reusing when confirming */
        *(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash;
+       ct->status = 0;
        /* Don't set timer yet: wait for confirmation */
        setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct);
        write_pnet(&ct->ct_net, net);
+       memset(&ct->__nfct_init_offset[0], 0,
+              offsetof(struct nf_conn, proto) -
+              offsetof(struct nf_conn, __nfct_init_offset[0]));
 #ifdef CONFIG_NF_CONNTRACK_ZONES
        if (zone) {
                struct nf_conntrack_zone *nf_ct_zone;