pipe: reopen pipes via usernsd

Submitted by Andrei Vagin on Feb. 28, 2017, 7:26 a.m.

Details

Message ID 1488266760-6647-1-git-send-email-avagin@openvz.org
State Accepted
Series "pipe: reopen pipes via usernsd"
Headers show

Commit Message

Andrei Vagin Feb. 28, 2017, 7:26 a.m.
From: Andrei Vagin <avagin@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@virtuozzo.com>
---
 criu/pipes.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

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;

Comments

Cyrill Gorcunov Feb. 28, 2017, 7:42 a.m.
On Tue, Feb 28, 2017 at 10:26:00AM +0300, Andrei Vagin wrote:
> From: Andrei Vagin <avagin@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@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Andrey Vagin March 16, 2017, 9:50 p.m.
Applied

On Tue, Feb 28, 2017 at 10:26:00AM +0300, Andrei Vagin wrote:
> From: Andrei Vagin <avagin@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@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
>