[CRIU] [PATCH] pipe: reopen pipes via usernsd

Andrei Vagin avagin at openvz.org
Mon Feb 27 23:26:00 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

If a pipe is inherited (external), it may be impossible to reopen it
from a restored user namespace due to lack of permession,
so in this case we have to reopen it via usernsd.

https://github.com/opencontainers/runc/issues/1333
Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/pipes.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/criu/pipes.c b/criu/pipes.c
index d665a59..4d15d73 100644
--- a/criu/pipes.c
+++ b/criu/pipes.c
@@ -17,6 +17,7 @@
 #include "images/pipe.pb-c.h"
 #include "images/pipe-data.pb-c.h"
 #include "fcntl.h"
+#include "namespaces.h"
 
 static LIST_HEAD(pipes);
 
@@ -213,10 +214,10 @@ err:
 	return ret;
 }
 
-static int reopen_pipe(int fd, int flags)
+static int userns_reopen(void *_arg, int fd, pid_t pid)
 {
-	int ret;
 	char path[PSFDS];
+	int ret, flags = *(int*)_arg;
 
 	sprintf(path, "/proc/self/fd/%d", fd);
 	ret = open(path, flags);
@@ -227,6 +228,26 @@ static int reopen_pipe(int fd, int flags)
 	return ret;
 }
 
+static int reopen_pipe(int fd, int flags)
+{
+	int ret;
+	char path[PSFDS];
+
+	sprintf(path, "/proc/self/fd/%d", fd);
+	ret = open(path, flags);
+	if (ret < 0) {
+		if (errno == EACCES) {
+			/* It may be an external pipe from an another userns */
+			ret = userns_call(userns_reopen, UNS_FDOUT,
+						&flags, sizeof(flags), fd);
+		} else
+			pr_perror("Unable to reopen the pipe %s", path);
+	}
+	close(fd);
+
+	return ret;
+}
+
 static int recv_pipe_fd(struct pipe_info *pi, int *new_fd)
 {
 	int tmp, fd, ret;
-- 
2.7.4



More information about the CRIU mailing list