Skip to content

Commit

Permalink
netfilter: nf_conntrack: fix memory corruption with multiple namespaces
Browse files Browse the repository at this point in the history
As discovered by Jon Masters <jonathan@jonmasters.org>, the "untracked"
conntrack, which is located in the data section, might be accidentally
freed when a new namespace is instantiated while the untracked conntrack
is attached to a skb because the reference count it re-initialized.

The best fix would be to use a seperate untracked conntrack per
namespace since it includes a namespace pointer. Unfortunately this is
not possible without larger changes since the namespace is not easily
available everywhere we need it. For now move the untracked conntrack
initialization to the init_net setup function to make sure the reference
count is not re-initialized and handle cleanup in the init_net cleanup
function to make sure namespaces can exit properly while the untracked
conntrack is in use in other namespaces.

Cc: stable@kernel.org
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
kaber authored and davem330 committed Feb 8, 2010
1 parent 1b3f720 commit 9edd7ca
Showing 1 changed file with 12 additions and 12 deletions.
24 changes: 12 additions & 12 deletions net/netfilter/nf_conntrack_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,10 @@ static void nf_ct_release_dying_list(struct net *net)

static void nf_conntrack_cleanup_init_net(void)
{
/* wait until all references to nf_conntrack_untracked are dropped */
while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
schedule();

nf_conntrack_helper_fini();
nf_conntrack_proto_fini();
kmem_cache_destroy(nf_conntrack_cachep);
Expand All @@ -1127,9 +1131,6 @@ static void nf_conntrack_cleanup_net(struct net *net)
schedule();
goto i_see_dead_people;
}
/* wait until all references to nf_conntrack_untracked are dropped */
while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
schedule();

nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
nf_conntrack_htable_size);
Expand Down Expand Up @@ -1288,6 +1289,14 @@ static int nf_conntrack_init_init_net(void)
if (ret < 0)
goto err_helper;

/* Set up fake conntrack: to never be deleted, not in any hashes */
#ifdef CONFIG_NET_NS
nf_conntrack_untracked.ct_net = &init_net;
#endif
atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);

return 0;

err_helper:
Expand Down Expand Up @@ -1333,15 +1342,6 @@ static int nf_conntrack_init_net(struct net *net)
if (ret < 0)
goto err_ecache;

/* Set up fake conntrack:
- to never be deleted, not in any hashes */
#ifdef CONFIG_NET_NS
nf_conntrack_untracked.ct_net = &init_net;
#endif
atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);

return 0;

err_ecache:
Expand Down

0 comments on commit 9edd7ca

Please sign in to comment.