Commit 0d0ad8b1 authored by Yi-Hung Wei's avatar Yi-Hung Wei Committed by Kleber Sacilotto de Souza

netfilter: nf_conncount: Fix garbage collection with zones

BugLink: https://bugs.launchpad.net/bugs/1811094

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: e59ea3df ("netfilter: xt_connlimit: honor conntrack zone if available")
Signed-off-by: default avatarYi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
(backported from commit 21ba8847)
[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 35d8deb8 ("netfilter: conncount: Support count only use case")
     which addresses nf_conncount_count() that does not exist yet -- it's introduced by
     upstream commit 625c5561 ("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: default avatarMauricio Faria de Oliveira <mfo@canonical.com>
Acked-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
Acked-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 465eeceb
...@@ -7,7 +7,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, ...@@ -7,7 +7,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
bool *addit); bool *addit);
bool nf_conncount_add(struct hlist_head *head, 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); void nf_conncount_cache_free(struct hlist_head *hhead);
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
struct xt_connlimit_conn { struct xt_connlimit_conn {
struct hlist_node node; struct hlist_node node;
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
struct nf_conntrack_zone zone;
}; };
struct xt_connlimit_rb { struct xt_connlimit_rb {
...@@ -116,7 +117,8 @@ same_source_net(const union nf_inet_addr *addr, ...@@ -116,7 +117,8 @@ same_source_net(const union nf_inet_addr *addr,
} }
bool nf_conncount_add(struct hlist_head *head, 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; struct xt_connlimit_conn *conn;
...@@ -124,6 +126,7 @@ bool nf_conncount_add(struct hlist_head *head, ...@@ -124,6 +126,7 @@ bool nf_conncount_add(struct hlist_head *head,
if (conn == NULL) if (conn == NULL)
return false; return false;
conn->tuple = *tuple; conn->tuple = *tuple;
conn->zone = *zone;
hlist_add_head(&conn->node, head); hlist_add_head(&conn->node, head);
return true; return true;
} }
...@@ -145,7 +148,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, ...@@ -145,7 +148,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
/* check the saved connections */ /* check the saved connections */
hlist_for_each_entry_safe(conn, n, head, node) { 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) { if (found == NULL) {
hlist_del(&conn->node); hlist_del(&conn->node);
kmem_cache_free(connlimit_conn_cachep, conn); kmem_cache_free(connlimit_conn_cachep, conn);
...@@ -154,7 +157,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, ...@@ -154,7 +157,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
found_ct = nf_ct_tuplehash_to_ctrack(found); 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. * Just to be sure we have it only once in the list.
* We should not see tuples twice unless someone hooks * We should not see tuples twice unless someone hooks
...@@ -235,7 +239,7 @@ count_tree(struct net *net, struct rb_root *root, ...@@ -235,7 +239,7 @@ count_tree(struct net *net, struct rb_root *root,
if (!addit) if (!addit)
return count; return count;
if (!nf_conncount_add(&rbconn->hhead, tuple)) if (!nf_conncount_add(&rbconn->hhead, tuple, zone))
return 0; /* hotdrop */ return 0; /* hotdrop */
return count + 1; return count + 1;
...@@ -274,6 +278,7 @@ count_tree(struct net *net, struct rb_root *root, ...@@ -274,6 +278,7 @@ count_tree(struct net *net, struct rb_root *root,
} }
conn->tuple = *tuple; conn->tuple = *tuple;
conn->zone = *zone;
rbconn->addr = *addr; rbconn->addr = *addr;
INIT_HLIST_HEAD(&rbconn->hhead); INIT_HLIST_HEAD(&rbconn->hhead);
......
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