Commit 9cf94eab authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Pablo Neira Ayuso

netfilter: conntrack: use nf_ct_tmpl_free in CT/synproxy error paths

Commit 0838aa7f ("netfilter: fix netns dependencies with conntrack
templates") migrated templates to the new allocator api, but forgot to
update error paths for them in CT and synproxy to use nf_ct_tmpl_free()
instead of nf_conntrack_free().

Due to that, memory is being freed into the wrong kmemcache, but also
we drop the per net reference count of ct objects causing an imbalance.

In Brad's case, this leads to a wrap-around of net->ct.count and thus
lets __nf_conntrack_alloc() refuse to create a new ct object:

  [   10.340913] xt_addrtype: ipv6 does not support BROADCAST matching
  [   10.810168] nf_conntrack: table full, dropping packet
  [   11.917416] r8169 0000:07:00.0 eth0: link up
  [   11.917438] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
  [   12.815902] nf_conntrack: table full, dropping packet
  [   15.688561] nf_conntrack: table full, dropping packet
  [   15.689365] nf_conntrack: table full, dropping packet
  [   15.690169] nf_conntrack: table full, dropping packet
  [   15.690967] nf_conntrack: table full, dropping packet
  [...]

With slab debugging, it also reports the wrong kmemcache (kmalloc-512 vs.
nf_conntrack_ffffffff81ce75c0) and reports poison overwrites, etc. Thus,
to fix the problem, export and use nf_ct_tmpl_free() instead.

Fixes: 0838aa7f ("netfilter: fix netns dependencies with conntrack templates")
Reported-by: default avatarBrad Jackson <bjackson0971@gmail.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent a9de9777
...@@ -292,6 +292,7 @@ extern unsigned int nf_conntrack_hash_rnd; ...@@ -292,6 +292,7 @@ extern unsigned int nf_conntrack_hash_rnd;
void init_nf_conntrack_hash_rnd(void); void init_nf_conntrack_hash_rnd(void);
struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags); struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags);
void nf_ct_tmpl_free(struct nf_conn *tmpl);
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
......
...@@ -320,12 +320,13 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags) ...@@ -320,12 +320,13 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags)
} }
EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc); EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc);
static void nf_ct_tmpl_free(struct nf_conn *tmpl) void nf_ct_tmpl_free(struct nf_conn *tmpl)
{ {
nf_ct_ext_destroy(tmpl); nf_ct_ext_destroy(tmpl);
nf_ct_ext_free(tmpl); nf_ct_ext_free(tmpl);
kfree(tmpl); kfree(tmpl);
} }
EXPORT_SYMBOL_GPL(nf_ct_tmpl_free);
static void static void
destroy_conntrack(struct nf_conntrack *nfct) destroy_conntrack(struct nf_conntrack *nfct)
......
...@@ -378,7 +378,7 @@ static int __net_init synproxy_net_init(struct net *net) ...@@ -378,7 +378,7 @@ static int __net_init synproxy_net_init(struct net *net)
err3: err3:
free_percpu(snet->stats); free_percpu(snet->stats);
err2: err2:
nf_conntrack_free(ct); nf_ct_tmpl_free(ct);
err1: err1:
return err; return err;
} }
......
...@@ -233,7 +233,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par, ...@@ -233,7 +233,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
return 0; return 0;
err3: err3:
nf_conntrack_free(ct); nf_ct_tmpl_free(ct);
err2: err2:
nf_ct_l3proto_module_put(par->family); nf_ct_l3proto_module_put(par->family);
err1: err1:
......
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