Jesse Keating 7a32965
Jon Masters correctly points out that conntrack hash sizes
Jesse Keating 7a32965
(nf_conntrack_htable_size) are global (not per-netns) and
Jesse Keating 7a32965
modifiable at runtime via /sys/module/nf_conntrack/hashsize .
Jesse Keating 7a32965
Jesse Keating 7a32965
Steps to reproduce:
Jesse Keating 7a32965
	clone(CLONE_NEWNET)
Jesse Keating 7a32965
	[grow /sys/module/nf_conntrack/hashsize]
Jesse Keating 7a32965
	exit()
Jesse Keating 7a32965
Jesse Keating 7a32965
At netns exit we are going to scan random memory for conntracks to be killed.
Jesse Keating 7a32965
Jesse Keating 7a32965
Apparently there is a code which deals with hashtable resize for
Jesse Keating 7a32965
init_net (and it was there befode netns conntrack code), so prohibit
Jesse Keating 7a32965
hashsize modification if there is more than one netns exists.
Jesse Keating 7a32965
Jesse Keating 7a32965
To change hashtable sizes, you need to reload module.
Jesse Keating 7a32965
Jesse Keating 7a32965
Expectation hashtable size was simply glued to a variable with no code
Jesse Keating 7a32965
to rehash expectations, so it was a bug to allow writing to it.
Jesse Keating 7a32965
Make "expect_hashsize" readonly.
Jesse Keating 7a32965
Jesse Keating 7a32965
This is temporarily until we figure out what to do.
Jesse Keating 7a32965
Jesse Keating 7a32965
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Jesse Keating 7a32965
Cc: stable@kernel.org
Jesse Keating 7a32965
---
Jesse Keating 7a32965
Jesse Keating 7a32965
 net/netfilter/nf_conntrack_core.c   |   15 +++++++++++++++
Jesse Keating 7a32965
 net/netfilter/nf_conntrack_expect.c |    2 +-
Jesse Keating 7a32965
 2 files changed, 16 insertions(+), 1 deletion(-)
Jesse Keating 7a32965
Jesse Keating 7a32965
--- a/net/netfilter/nf_conntrack_core.c
Jesse Keating 7a32965
+++ b/net/netfilter/nf_conntrack_core.c
Jesse Keating 7a32965
@@ -21,6 +21,7 @@
Jesse Keating 7a32965
 #include <linux/stddef.h>
Jesse Keating 7a32965
 #include <linux/slab.h>
Jesse Keating 7a32965
 #include <linux/random.h>
Jesse Keating 7a32965
+#include <linux/rtnetlink.h>
Jesse Keating 7a32965
 #include <linux/jhash.h>
Jesse Keating 7a32965
 #include <linux/err.h>
Jesse Keating 7a32965
 #include <linux/percpu.h>
Jesse Keating 7a32965
@@ -1198,6 +1199,20 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
Jesse Keating 7a32965
 	if (!nf_conntrack_htable_size)
Jesse Keating 7a32965
 		return param_set_uint(val, kp);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
+	{
Jesse Keating 7a32965
+		struct net *net;
Jesse Keating 7a32965
+		unsigned int nr;
Jesse Keating 7a32965
+
Jesse Keating 7a32965
+		nr = 0;
Jesse Keating 7a32965
+		rtnl_lock();
Jesse Keating 7a32965
+		for_each_net(net)
Jesse Keating 7a32965
+			nr++;
Jesse Keating 7a32965
+		rtnl_unlock();
Jesse Keating 7a32965
+		/* init_net always exists */
Jesse Keating 7a32965
+		if (nr != 1)
Jesse Keating 7a32965
+			return -EINVAL;
Jesse Keating 7a32965
+	}
Jesse Keating 7a32965
+
Jesse Keating 7a32965
 	hashsize = simple_strtoul(val, NULL, 0);
Jesse Keating 7a32965
 	if (!hashsize)
Jesse Keating 7a32965
 		return -EINVAL;
Jesse Keating 7a32965
--- a/net/netfilter/nf_conntrack_expect.c
Jesse Keating 7a32965
+++ b/net/netfilter/nf_conntrack_expect.c
Jesse Keating 7a32965
@@ -569,7 +569,7 @@ static void exp_proc_remove(struct net *net)
Jesse Keating 7a32965
 #endif /* CONFIG_PROC_FS */
Jesse Keating 7a32965
 }
Jesse Keating 7a32965
 
Jesse Keating 7a32965
-module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
Jesse Keating 7a32965
+module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0400);
Jesse Keating 7a32965
 
Jesse Keating 7a32965
 int nf_conntrack_expect_init(struct net *net)
Jesse Keating 7a32965
 {
Jesse Keating 7a32965