]>
Commit | Line | Data |
---|---|---|
739e1c91 GKH |
1 | From 9edd7ca0a3e3999c260642c92fa008892d82ca6e Mon Sep 17 00:00:00 2001 |
2 | From: Patrick McHardy <kaber@trash.net> | |
3 | Date: Mon, 8 Feb 2010 11:16:26 -0800 | |
4 | Subject: netfilter: nf_conntrack: fix memory corruption with multiple namespaces | |
5 | ||
6 | From: Patrick McHardy <kaber@trash.net> | |
7 | ||
8 | commit 9edd7ca0a3e3999c260642c92fa008892d82ca6e upstream. | |
9 | ||
10 | As discovered by Jon Masters <jonathan@jonmasters.org>, the "untracked" | |
11 | conntrack, which is located in the data section, might be accidentally | |
12 | freed when a new namespace is instantiated while the untracked conntrack | |
13 | is attached to a skb because the reference count it re-initialized. | |
14 | ||
15 | The best fix would be to use a seperate untracked conntrack per | |
16 | namespace since it includes a namespace pointer. Unfortunately this is | |
17 | not possible without larger changes since the namespace is not easily | |
18 | available everywhere we need it. For now move the untracked conntrack | |
19 | initialization to the init_net setup function to make sure the reference | |
20 | count is not re-initialized and handle cleanup in the init_net cleanup | |
21 | function to make sure namespaces can exit properly while the untracked | |
22 | conntrack is in use in other namespaces. | |
23 | ||
24 | Signed-off-by: Patrick McHardy <kaber@trash.net> | |
25 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
26 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
27 | ||
28 | --- | |
29 | net/netfilter/nf_conntrack_core.c | 24 ++++++++++++------------ | |
30 | 1 file changed, 12 insertions(+), 12 deletions(-) | |
31 | ||
32 | --- a/net/netfilter/nf_conntrack_core.c | |
33 | +++ b/net/netfilter/nf_conntrack_core.c | |
34 | @@ -1107,6 +1107,10 @@ static void nf_ct_release_dying_list(str | |
35 | ||
36 | static void nf_conntrack_cleanup_init_net(void) | |
37 | { | |
38 | + /* wait until all references to nf_conntrack_untracked are dropped */ | |
39 | + while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) | |
40 | + schedule(); | |
41 | + | |
42 | nf_conntrack_helper_fini(); | |
43 | nf_conntrack_proto_fini(); | |
44 | kmem_cache_destroy(nf_conntrack_cachep); | |
45 | @@ -1121,9 +1125,6 @@ static void nf_conntrack_cleanup_net(str | |
46 | schedule(); | |
47 | goto i_see_dead_people; | |
48 | } | |
49 | - /* wait until all references to nf_conntrack_untracked are dropped */ | |
50 | - while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) | |
51 | - schedule(); | |
52 | ||
53 | nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, | |
54 | nf_conntrack_htable_size); | |
55 | @@ -1282,6 +1283,14 @@ static int nf_conntrack_init_init_net(vo | |
56 | if (ret < 0) | |
57 | goto err_helper; | |
58 | ||
59 | + /* Set up fake conntrack: to never be deleted, not in any hashes */ | |
60 | +#ifdef CONFIG_NET_NS | |
61 | + nf_conntrack_untracked.ct_net = &init_net; | |
62 | +#endif | |
63 | + atomic_set(&nf_conntrack_untracked.ct_general.use, 1); | |
64 | + /* - and look it like as a confirmed connection */ | |
65 | + set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status); | |
66 | + | |
67 | return 0; | |
68 | ||
69 | err_helper: | |
70 | @@ -1327,15 +1336,6 @@ static int nf_conntrack_init_net(struct | |
71 | if (ret < 0) | |
72 | goto err_ecache; | |
73 | ||
74 | - /* Set up fake conntrack: | |
75 | - - to never be deleted, not in any hashes */ | |
76 | -#ifdef CONFIG_NET_NS | |
77 | - nf_conntrack_untracked.ct_net = &init_net; | |
78 | -#endif | |
79 | - atomic_set(&nf_conntrack_untracked.ct_general.use, 1); | |
80 | - /* - and look it like as a confirmed connection */ | |
81 | - set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status); | |
82 | - | |
83 | return 0; | |
84 | ||
85 | err_ecache: |