[CRIU] [PATCH] net: block all traffic in internal network (v3)

Andrey Vagin avagin at openvz.org
Thu Nov 19 05:12:57 PST 2015


From: Andrew Vagin <avagin at openvz.org>

Let's imagine that we have two local interconnected sockets.
Whe we are restoring tcp sockets, we need to disable the repair mode
to restore data in sending queues.

If traffic isn't blocked, a socket starts operating, but
in this time another end can be not restored yet.

$ test/zdtm.sh -r ns/static/socket-tcpbuf-local
...
(00.274632) 5: Error (sk-tcp.c:485): Can't restore 2 queue data (-1), want (1780919:1780919): Connection reset by peer

We create a separate chain to avoid conflicts with other rules.

https://bugs.openvz.org/browse/CRIU-96

v2: use iptables-restore to apply whole configuration for one call
v3: add a comment why we use iptables-restore instread of iptables.
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 net.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 90 insertions(+), 2 deletions(-)

diff --git a/net.c b/net.c
index 975de1e..b361ea9 100644
--- a/net.c
+++ b/net.c
@@ -955,6 +955,89 @@ int netns_keep_nsfd(void)
 	pr_info("Saved netns fd for links restore\n");
 	return 0;
 }
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/*
+ * If we want to modify iptables, we need to recevied the current
+ * configuration, change it and load a new one into the kernel.
+ * iptables can change or add only one rule.
+ * iptables-restore allows to make a few changes for one iteration,
+ * so it works faster.
+ */
+static int iptables_restore(bool ipv6, char *buf, int size)
+{
+	int pfd[2], ret = -1;
+	char *cmd4[] = {"iptables-restore",  "--noflush", NULL};
+	char *cmd6[] = {"ip6tables-restore", "--noflush", NULL};
+	char **cmd = ipv6 ? cmd6 : cmd4;;
+
+	if (pipe(pfd) < 0) {
+		pr_perror("Unable to create pipe");
+		return -1;
+	}
+
+	if (write(pfd[1], buf, size) < size) {
+		pr_perror("Unable to write iptables configugration");
+		goto err;
+	}
+	close_safe(&pfd[1]);
+
+	ret = cr_system(pfd[0], -1, -1, cmd[0], cmd, 0);
+err:
+	close_safe(&pfd[1]);
+	close_safe(&pfd[0]);
+	return ret;
+}
+
+static int network_lock_internal()
+{
+	char conf[] =	"*filter\n"
+				":CRIU - [0:0]\n"
+				"-I INPUT -j CRIU\n"
+				"-I OUTPUT -j CRIU\n"
+				"-A CRIU -j DROP\n"
+				"COMMIT\n";
+	int ret = 0, nsret;
+
+	if (switch_ns(root_item->pid.real, &net_ns_desc, &nsret))
+		return -1;
+
+
+	ret |= iptables_restore(false, conf, sizeof(conf) - 1);
+	if (kdat.ipv6)
+		ret |= iptables_restore(true, conf, sizeof(conf) - 1);
+
+	if (restore_ns(nsret, &net_ns_desc))
+		ret = -1;
+
+	return ret;
+}
+
+static int network_unlock_internal()
+{
+	char conf[] =	"*filter\n"
+			":CRIU - [0:0]\n"
+			"-D INPUT -j CRIU\n"
+			"-D OUTPUT -j CRIU\n"
+			"-X CRIU\n"
+			"COMMIT\n";
+	int ret = 0, nsret;
+
+	if (switch_ns(root_item->pid.real, &net_ns_desc, &nsret))
+		return -1;
+
+
+	ret |= iptables_restore(false, conf, sizeof(conf) - 1);
+	if (kdat.ipv6)
+		ret |= iptables_restore(true, conf, sizeof(conf) - 1);
+
+	if (restore_ns(nsret, &net_ns_desc))
+		ret = -1;
+
+	return ret;
+}
 
 int network_lock(void)
 {
@@ -964,7 +1047,10 @@ int network_lock(void)
 	if  (!(root_ns_mask & CLONE_NEWNET))
 		return 0;
 
-	return run_scripts(ACT_NET_LOCK);
+	if (run_scripts(ACT_NET_LOCK))
+		return -1;
+
+	return network_lock_internal();
 }
 
 void network_unlock(void)
@@ -974,8 +1060,10 @@ void network_unlock(void)
 	cpt_unlock_tcp_connections();
 	rst_unlock_tcp_connections();
 
-	if (root_ns_mask & CLONE_NEWNET)
+	if (root_ns_mask & CLONE_NEWNET) {
 		run_scripts(ACT_NET_UNLOCK);
+		network_unlock_internal();
+	}
 }
 
 int veth_pair_add(char *in, char *out)
-- 
2.4.3



More information about the CRIU mailing list