[v3,26/33] utils: Introduce open_fd_of_real_pid()

Submitted by Kirill Tkhai on Feb. 16, 2017, 12:10 p.m.

Details

Message ID 148724702445.22444.17534637113336791433.stgit@localhost.localdomain
State New
Series "Nested user namespaces support"
Headers show

Commit Message

Kirill Tkhai Feb. 16, 2017, 12:10 p.m.
As access to /proc/[pid]/fd/[i] of a task from parent's
user_ns is prohibited, introduce a helper, doing that
via usernsd.

Also, remove BUG_ON() in usernsd, as now it may be used
without input fd parameter.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/include/util.h |    2 ++
 criu/namespaces.c   |    5 -----
 criu/util.c         |   30 ++++++++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/util.h b/criu/include/util.h
index d9f50f6e0..c1d38c939 100644
--- a/criu/include/util.h
+++ b/criu/include/util.h
@@ -307,4 +307,6 @@  extern int epoll_del_rfd(int epfd, struct epoll_rfd *rfd);
 extern int epoll_run_rfds(int epfd, struct epoll_event *evs, int nr_fds, int tmo);
 extern int epoll_prepare(int nr_events, struct epoll_event **evs);
 
+extern int open_fd_of_real_pid(pid_t pid, int fd, int flags);
+
 #endif /* __CR_UTIL_H__ */
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 518b0af4e..bf4c16d08 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -1447,11 +1447,6 @@  static int usernsd(int sk)
 		unsc_msg_pid_fd(&um, &pid, &fd);
 		pr_debug("uns: daemon calls %p (%d, %d, %x)\n", call, pid, fd, flags);
 
-		if (fd < 0 && flags & UNS_FDOUT) {
-			pr_err("uns: bad flags/fd %p %d %x\n", call, fd, flags);
-			BUG();
-		}
-
 		/*
 		 * Caller has sent us bare address of the routine it
 		 * wants to call. Since the caller is fork()-ed from the
diff --git a/criu/util.c b/criu/util.c
index 6e36b2654..51adcd3d7 100644
--- a/criu/util.c
+++ b/criu/util.c
@@ -1315,3 +1315,33 @@  int epoll_prepare(int nr_fds, struct epoll_event **events)
 	xfree(*events);
 	return -1;
 }
+
+static int fn_open_proc_r(void *path, int fd, pid_t pid)
+{
+	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDONLY);
+}
+static int fn_open_proc_w(void *path, int fd, pid_t pid)
+{
+	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_WRONLY);
+}
+static int fn_open_proc_rw(void *path, int fd, pid_t pid)
+{
+	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDWR);
+}
+
+int open_fd_of_real_pid(pid_t pid, int fd, int flags)
+{
+	char path[64];
+	int ret;
+
+	ret = sprintf(path, "%d/fd/%d", pid, fd);
+	if (flags == O_RDONLY)
+		ret = userns_call(fn_open_proc_r, UNS_FDOUT, path, ret + 1, -1);
+	else if (flags == O_WRONLY)
+		ret = userns_call(fn_open_proc_w, UNS_FDOUT, path, ret + 1, -1);
+	else if (flags == O_RDWR)
+		ret = userns_call(fn_open_proc_rw, UNS_FDOUT, path, ret + 1, -1);
+	else
+		BUG();
+	return ret;
+}

Comments

Andrey Vagin Feb. 21, 2017, 7:36 a.m.
On Thu, Feb 16, 2017 at 03:10:24PM +0300, Kirill Tkhai wrote:
> As access to /proc/[pid]/fd/[i] of a task from parent's
> user_ns is prohibited, introduce a helper, doing that
> via usernsd.

Could you explain where are you going to use it?
> 
> Also, remove BUG_ON() in usernsd, as now it may be used
> without input fd parameter.
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> ---
>  criu/include/util.h |    2 ++
>  criu/namespaces.c   |    5 -----
>  criu/util.c         |   30 ++++++++++++++++++++++++++++++
>  3 files changed, 32 insertions(+), 5 deletions(-)
> 
> diff --git a/criu/include/util.h b/criu/include/util.h
> index d9f50f6e0..c1d38c939 100644
> --- a/criu/include/util.h
> +++ b/criu/include/util.h
> @@ -307,4 +307,6 @@ extern int epoll_del_rfd(int epfd, struct epoll_rfd *rfd);
>  extern int epoll_run_rfds(int epfd, struct epoll_event *evs, int nr_fds, int tmo);
>  extern int epoll_prepare(int nr_events, struct epoll_event **evs);
>  
> +extern int open_fd_of_real_pid(pid_t pid, int fd, int flags);
> +
>  #endif /* __CR_UTIL_H__ */
> diff --git a/criu/namespaces.c b/criu/namespaces.c
> index 518b0af4e..bf4c16d08 100644
> --- a/criu/namespaces.c
> +++ b/criu/namespaces.c
> @@ -1447,11 +1447,6 @@ static int usernsd(int sk)
>  		unsc_msg_pid_fd(&um, &pid, &fd);
>  		pr_debug("uns: daemon calls %p (%d, %d, %x)\n", call, pid, fd, flags);
>  
> -		if (fd < 0 && flags & UNS_FDOUT) {
> -			pr_err("uns: bad flags/fd %p %d %x\n", call, fd, flags);
> -			BUG();
> -		}
> -
>  		/*
>  		 * Caller has sent us bare address of the routine it
>  		 * wants to call. Since the caller is fork()-ed from the
> diff --git a/criu/util.c b/criu/util.c
> index 6e36b2654..51adcd3d7 100644
> --- a/criu/util.c
> +++ b/criu/util.c
> @@ -1315,3 +1315,33 @@ int epoll_prepare(int nr_fds, struct epoll_event **events)
>  	xfree(*events);
>  	return -1;
>  }
> +
> +static int fn_open_proc_r(void *path, int fd, pid_t pid)
> +{
> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDONLY);
> +}
> +static int fn_open_proc_w(void *path, int fd, pid_t pid)
> +{
> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_WRONLY);
> +}
> +static int fn_open_proc_rw(void *path, int fd, pid_t pid)
> +{
> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDWR);
> +}
> +
> +int open_fd_of_real_pid(pid_t pid, int fd, int flags)
> +{
> +	char path[64];
> +	int ret;
> +
> +	ret = sprintf(path, "%d/fd/%d", pid, fd);
> +	if (flags == O_RDONLY)
> +		ret = userns_call(fn_open_proc_r, UNS_FDOUT, path, ret + 1, -1);
> +	else if (flags == O_WRONLY)
> +		ret = userns_call(fn_open_proc_w, UNS_FDOUT, path, ret + 1, -1);
> +	else if (flags == O_RDWR)
> +		ret = userns_call(fn_open_proc_rw, UNS_FDOUT, path, ret + 1, -1);
> +	else
> +		BUG();
> +	return ret;
> +}
> 
> _______________________________________________
> CRIU mailing list
> CRIU@openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
Kirill Tkhai Feb. 21, 2017, 12:12 p.m.
On 21.02.2017 10:36, Andrei Vagin wrote:
> On Thu, Feb 16, 2017 at 03:10:24PM +0300, Kirill Tkhai wrote:
>> As access to /proc/[pid]/fd/[i] of a task from parent's
>> user_ns is prohibited, introduce a helper, doing that
>> via usernsd.
> 
> Could you explain where are you going to use it?

In "[PATCH v3 29/33] shmem: Fixup shmem_wait_and_open() opens foreign /proc/[pid]/fd/[i]"

>>
>> Also, remove BUG_ON() in usernsd, as now it may be used
>> without input fd parameter.
>>
>> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
>> ---
>>  criu/include/util.h |    2 ++
>>  criu/namespaces.c   |    5 -----
>>  criu/util.c         |   30 ++++++++++++++++++++++++++++++
>>  3 files changed, 32 insertions(+), 5 deletions(-)
>>
>> diff --git a/criu/include/util.h b/criu/include/util.h
>> index d9f50f6e0..c1d38c939 100644
>> --- a/criu/include/util.h
>> +++ b/criu/include/util.h
>> @@ -307,4 +307,6 @@ extern int epoll_del_rfd(int epfd, struct epoll_rfd *rfd);
>>  extern int epoll_run_rfds(int epfd, struct epoll_event *evs, int nr_fds, int tmo);
>>  extern int epoll_prepare(int nr_events, struct epoll_event **evs);
>>  
>> +extern int open_fd_of_real_pid(pid_t pid, int fd, int flags);
>> +
>>  #endif /* __CR_UTIL_H__ */
>> diff --git a/criu/namespaces.c b/criu/namespaces.c
>> index 518b0af4e..bf4c16d08 100644
>> --- a/criu/namespaces.c
>> +++ b/criu/namespaces.c
>> @@ -1447,11 +1447,6 @@ static int usernsd(int sk)
>>  		unsc_msg_pid_fd(&um, &pid, &fd);
>>  		pr_debug("uns: daemon calls %p (%d, %d, %x)\n", call, pid, fd, flags);
>>  
>> -		if (fd < 0 && flags & UNS_FDOUT) {
>> -			pr_err("uns: bad flags/fd %p %d %x\n", call, fd, flags);
>> -			BUG();
>> -		}
>> -
>>  		/*
>>  		 * Caller has sent us bare address of the routine it
>>  		 * wants to call. Since the caller is fork()-ed from the
>> diff --git a/criu/util.c b/criu/util.c
>> index 6e36b2654..51adcd3d7 100644
>> --- a/criu/util.c
>> +++ b/criu/util.c
>> @@ -1315,3 +1315,33 @@ int epoll_prepare(int nr_fds, struct epoll_event **events)
>>  	xfree(*events);
>>  	return -1;
>>  }
>> +
>> +static int fn_open_proc_r(void *path, int fd, pid_t pid)
>> +{
>> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDONLY);
>> +}
>> +static int fn_open_proc_w(void *path, int fd, pid_t pid)
>> +{
>> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_WRONLY);
>> +}
>> +static int fn_open_proc_rw(void *path, int fd, pid_t pid)
>> +{
>> +	return openat(get_service_fd(CR_PROC_FD_OFF), path, O_RDWR);
>> +}
>> +
>> +int open_fd_of_real_pid(pid_t pid, int fd, int flags)
>> +{
>> +	char path[64];
>> +	int ret;
>> +
>> +	ret = sprintf(path, "%d/fd/%d", pid, fd);
>> +	if (flags == O_RDONLY)
>> +		ret = userns_call(fn_open_proc_r, UNS_FDOUT, path, ret + 1, -1);
>> +	else if (flags == O_WRONLY)
>> +		ret = userns_call(fn_open_proc_w, UNS_FDOUT, path, ret + 1, -1);
>> +	else if (flags == O_RDWR)
>> +		ret = userns_call(fn_open_proc_rw, UNS_FDOUT, path, ret + 1, -1);
>> +	else
>> +		BUG();
>> +	return ret;
>> +}
>>
>> _______________________________________________
>> CRIU mailing list
>> CRIU@openvz.org
>> https://lists.openvz.org/mailman/listinfo/criu