From f9582b0bd3fb59307712da63872ff8fabe498bcc Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Thu, 23 Feb 2017 18:16:02 +0300 Subject: [PATCH] utils: Introduce open_fd_of_real_pid() 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 Signed-off-by: Andrei Vagin --- 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 1894f6acc..d65a7d866 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -331,4 +331,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 ee67bdad4..85444155c 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -1455,11 +1455,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 6f740630c..6b3eda69a 100644 --- a/criu/util.c +++ b/criu/util.c @@ -1386,3 +1386,33 @@ free_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; +}