Commit 2af17257 authored by Andrei Vagin's avatar Andrei Vagin Committed by Andrei Vagin

net: workaround a problem when iptables can't open /run/xtables.lock

Starting with iptables 1.6.2, we have to use the --wait option,
but it doesn't work properly with userns, because in this case,
we don't have enough rights to open /run/xtables.lock.

(00.174703)      1: 	Running iptables-restore -w for iptables-restore -w Fatal: can't open lock file /run/xtables.lock: Permission denied
(00.192058)      1: Error (criu/util.c:842): exited, status=4
(00.192080)      1: Error (criu/net.c:1738): iptables-restore -w failed
(00.192088)      1: Error (criu/net.c:2389): Can't create net_ns
(00.192131)      1: Error (criu/util.c:1567): Can't wait or bad status: errno=0, status=65280

This patch workarounds this problem by mounting tmpfs into /run.
Net namespaces are restored in a separate process, so we can create a
new mount namespace and create new mounts.

https://github.com/checkpoint-restore/criu/issues/469

Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@openvz.org>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 8a85222a
...@@ -1965,6 +1965,48 @@ out: ...@@ -1965,6 +1965,48 @@ out:
return ret; return ret;
} }
/*
* iptables-restore is executed from a target userns and it may have not enough
* rights to open /run/xtables.lock. Here we try to workaround this problem.
*/
static int prepare_xtable_lock()
{
int fd;
fd = open("/run/xtables.lock", O_RDONLY);
if (fd >= 0) {
close(fd);
return 0;
}
/*
* __prepare_net_namespaces is executed in a separate process,
* so a mount namespace can be changed.
*/
if (unshare(CLONE_NEWNS)) {
pr_perror("Unable to create a mount namespace");
return -1;
}
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
pr_perror("Unable to conver mounts to slave mounts");
return -1;
}
/*
* /run/xtables.lock may not exist, so we can't just bind-mount a file
* over it.
* A new mount will not be propagated to the host mount namespace,
* because we are in another userns.
*/
if (mount("criu-xtable-lock", "/run", "tmpfs", 0, NULL)) {
pr_perror("Unable to mount tmpfs into /run");
return -1;
}
return 0;
}
static inline int restore_iptables(int pid) static inline int restore_iptables(int pid)
{ {
int ret = -1; int ret = -1;
...@@ -2311,6 +2353,9 @@ static int __prepare_net_namespaces(void *unused) ...@@ -2311,6 +2353,9 @@ static int __prepare_net_namespaces(void *unused)
struct ns_id *nsid; struct ns_id *nsid;
int root_ns; int root_ns;
if (prepare_xtable_lock())
return -1;
root_ns = open_proc(PROC_SELF, "ns/net"); root_ns = open_proc(PROC_SELF, "ns/net");
if (root_ns < 0) if (root_ns < 0)
return -1; return -1;
......
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