4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

commit 21ba8847f857028dc83a0f341e16ecc616e34740 upstream.

Currently, we use check_hlist() for garbage colleciton. However, we
use the ‘zone’ from the counted entry to query the existence of
existing entries in the hlist. This could be wrong when they are in
different zones, and this patch fixes this issue.

Fixes: e59ea3df3fc2 ("netfilter: xt_connlimit: honor conntrack zone if 
available")
Signed-off-by: Yi-Hung Wei <yihung....@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>

[mfo: backport: refresh context lines and use older symbol/file names, note 
hunk 5:
 - nf_conncount.c -> xt_connlimit.c
   - nf_conncount_rb -> xt_connlimit_rb
   - nf_conncount_tuple -> xt_connlimit_conn
   - hunk 5: remove check for non-NULL 'tuple', that isn't required as it's 
introduced
     by upstream commit 35d8deb80 ("netfilter: conncount: Support count only 
use case")
     which addresses nf_conncount_count() that does not exist yet -- it's 
introduced by
     upstream commit 625c556118f3 ("netfilter: connlimit: split xt_connlimit 
into front
     and backend"), a refactor change.
 - nft_connlimit.c -> removed, not used/doesn't exist yet.]
Signed-off-by: Mauricio Faria de Oliveira <m...@canonical.com>

Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 include/net/netfilter/nf_conntrack_count.h |  3 ++-
 net/netfilter/xt_connlimit.c               | 13 +++++++++----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_count.h 
b/include/net/netfilter/nf_conntrack_count.h
index 54e43b8a8da1..4b71a2f4c351 100644
--- a/include/net/netfilter/nf_conntrack_count.h
+++ b/include/net/netfilter/nf_conntrack_count.h
@@ -7,7 +7,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct 
hlist_head *head,
                                 bool *addit);
 
 bool nf_conncount_add(struct hlist_head *head,
-                     const struct nf_conntrack_tuple *tuple);
+                     const struct nf_conntrack_tuple *tuple,
+                     const struct nf_conntrack_zone *zone);
 
 void nf_conncount_cache_free(struct hlist_head *hhead);
 
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 7af58750ab49..ab1f849464fa 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -46,6 +46,7 @@
 struct xt_connlimit_conn {
        struct hlist_node               node;
        struct nf_conntrack_tuple       tuple;
+       struct nf_conntrack_zone        zone;
 };
 
 struct xt_connlimit_rb {
@@ -115,7 +116,8 @@ same_source_net(const union nf_inet_addr *addr,
 }
 
 bool nf_conncount_add(struct hlist_head *head,
-                     const struct nf_conntrack_tuple *tuple)
+                     const struct nf_conntrack_tuple *tuple,
+                     const struct nf_conntrack_zone *zone)
 {
        struct xt_connlimit_conn *conn;
 
@@ -123,6 +125,7 @@ bool nf_conncount_add(struct hlist_head *head,
        if (conn == NULL)
                return false;
        conn->tuple = *tuple;
+       conn->zone = *zone;
        hlist_add_head(&conn->node, head);
        return true;
 }
@@ -143,7 +146,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct 
hlist_head *head,
 
        /* check the saved connections */
        hlist_for_each_entry_safe(conn, n, head, node) {
-               found = nf_conntrack_find_get(net, zone, &conn->tuple);
+               found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple);
                if (found == NULL) {
                        hlist_del(&conn->node);
                        kmem_cache_free(connlimit_conn_cachep, conn);
@@ -152,7 +155,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct 
hlist_head *head,
 
                found_ct = nf_ct_tuplehash_to_ctrack(found);
 
-               if (nf_ct_tuple_equal(&conn->tuple, tuple)) {
+               if (nf_ct_tuple_equal(&conn->tuple, tuple) &&
+                   nf_ct_zone_equal(found_ct, zone, zone->dir)) {
                        /*
                         * Just to be sure we have it only once in the list.
                         * We should not see tuples twice unless someone hooks
@@ -231,7 +235,7 @@ count_tree(struct net *net, struct rb_root *root,
                        if (!addit)
                                return count;
 
-                       if (!nf_conncount_add(&rbconn->hhead, tuple))
+                       if (!nf_conncount_add(&rbconn->hhead, tuple, zone))
                                return 0; /* hotdrop */
 
                        return count + 1;
@@ -270,6 +274,7 @@ count_tree(struct net *net, struct rb_root *root,
        }
 
        conn->tuple = *tuple;
+       conn->zone = *zone;
        rbconn->addr = *addr;
 
        INIT_HLIST_HEAD(&rbconn->hhead);
-- 
2.19.1



Reply via email to