Commit 252b3e8c authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: xt_CT: fix crash while destroy ct templates

In (d871befe netfilter: ctnetlink: dump entries from the dying and
unconfirmed lists), we assume that all conntrack objects are
inserted in any of the existing lists. However, template conntrack
objects were not. This results in hitting BUG_ON in the
destroy_conntrack path while removing a rule that uses the CT target.

This patch fixes the situation by adding the template lists, which
is where template conntrack objects reside now.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 0c36b48b
...@@ -71,6 +71,7 @@ struct netns_ct { ...@@ -71,6 +71,7 @@ struct netns_ct {
struct hlist_head *expect_hash; struct hlist_head *expect_hash;
struct hlist_nulls_head unconfirmed; struct hlist_nulls_head unconfirmed;
struct hlist_nulls_head dying; struct hlist_nulls_head dying;
struct hlist_nulls_head tmpl;
struct ip_conntrack_stat __percpu *stat; struct ip_conntrack_stat __percpu *stat;
struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb; struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
struct nf_exp_event_notifier __rcu *nf_expect_event_cb; struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
......
...@@ -1526,6 +1526,7 @@ static int nf_conntrack_init_init_net(void) ...@@ -1526,6 +1526,7 @@ static int nf_conntrack_init_init_net(void)
*/ */
#define UNCONFIRMED_NULLS_VAL ((1<<30)+0) #define UNCONFIRMED_NULLS_VAL ((1<<30)+0)
#define DYING_NULLS_VAL ((1<<30)+1) #define DYING_NULLS_VAL ((1<<30)+1)
#define TEMPLATE_NULLS_VAL ((1<<30)+2)
static int nf_conntrack_init_net(struct net *net) static int nf_conntrack_init_net(struct net *net)
{ {
...@@ -1534,6 +1535,7 @@ static int nf_conntrack_init_net(struct net *net) ...@@ -1534,6 +1535,7 @@ static int nf_conntrack_init_net(struct net *net)
atomic_set(&net->ct.count, 0); atomic_set(&net->ct.count, 0);
INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL); INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL);
INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL); INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL);
INIT_HLIST_NULLS_HEAD(&net->ct.tmpl, TEMPLATE_NULLS_VAL);
net->ct.stat = alloc_percpu(struct ip_conntrack_stat); net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
if (!net->ct.stat) { if (!net->ct.stat) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -149,6 +149,10 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) ...@@ -149,6 +149,10 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par)
__set_bit(IPS_TEMPLATE_BIT, &ct->status); __set_bit(IPS_TEMPLATE_BIT, &ct->status);
__set_bit(IPS_CONFIRMED_BIT, &ct->status); __set_bit(IPS_CONFIRMED_BIT, &ct->status);
/* Overload tuple linked list to put us in template list. */
hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
&par->net->ct.tmpl);
out: out:
info->ct = ct; info->ct = ct;
return 0; return 0;
...@@ -289,6 +293,10 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) ...@@ -289,6 +293,10 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
__set_bit(IPS_TEMPLATE_BIT, &ct->status); __set_bit(IPS_TEMPLATE_BIT, &ct->status);
__set_bit(IPS_CONFIRMED_BIT, &ct->status); __set_bit(IPS_CONFIRMED_BIT, &ct->status);
/* Overload tuple linked list to put us in template list. */
hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
&par->net->ct.tmpl);
out: out:
info->ct = ct; info->ct = ct;
return 0; return 0;
......
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