Commit a1457a7b authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

sysctl: restore sysctls for correct namespaces

When we don't use userns, __userns_sysctl_op is called
in context of the current process. A mount namespaces is restored
the last one, so when we restore namespaces, we see /proc from the
host pid namespace. In this case we can't use virtual pid to access
/proc/pid.

Let's open /proc/self/ns and use this descriptor to switch namespaces.

Cc: Tycho Andersen <tycho.andersen@canonical.com>
Fixes: f79f4546 ("sysctl: move sysctl calls to usernsd")
Signed-off-by: 's avatarAndrew Vagin <avagin@openvz.org>
Acked-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 23573119
...@@ -192,7 +192,7 @@ static int do_sysctl_op(int fd, struct sysctl_req *req, int op) ...@@ -192,7 +192,7 @@ static int do_sysctl_op(int fd, struct sysctl_req *req, int op)
return ret; return ret;
} }
static int __userns_sysctl_op(void *arg, int unused, pid_t pid) static int __userns_sysctl_op(void *arg, int proc_fd, pid_t pid)
{ {
int fd, ret = -1, dir, i, status, *fds = NULL; int fd, ret = -1, dir, i, status, *fds = NULL;
struct sysctl_userns_req *userns_req = arg; struct sysctl_userns_req *userns_req = arg;
...@@ -288,7 +288,7 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid) ...@@ -288,7 +288,7 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
const char *nsname = ns_to_string(userns_req->ns); const char *nsname = ns_to_string(userns_req->ns);
BUG_ON(!nsname); BUG_ON(!nsname);
nsfd = open_proc(pid, "ns/%s", nsname); nsfd = openat(proc_fd, nsname, O_RDONLY);
if (nsfd < 0) { if (nsfd < 0) {
pr_perror("failed to open pid %d's ns %s", pid, nsname); pr_perror("failed to open pid %d's ns %s", pid, nsname);
exit(1); exit(1);
...@@ -382,7 +382,7 @@ out: ...@@ -382,7 +382,7 @@ out:
int sysctl_op(struct sysctl_req *req, size_t nr_req, int op, unsigned int ns) int sysctl_op(struct sysctl_req *req, size_t nr_req, int op, unsigned int ns)
{ {
int i; int i, fd, ret;
struct sysctl_userns_req *userns_req; struct sysctl_userns_req *userns_req;
struct sysctl_req *cur; struct sysctl_req *cur;
...@@ -453,5 +453,11 @@ int sysctl_op(struct sysctl_req *req, size_t nr_req, int op, unsigned int ns) ...@@ -453,5 +453,11 @@ int sysctl_op(struct sysctl_req *req, size_t nr_req, int op, unsigned int ns)
cur = (struct sysctl_req *) (((char *) cur) + total_len); cur = (struct sysctl_req *) (((char *) cur) + total_len);
} }
return userns_call(__userns_sysctl_op, UNS_ASYNC, userns_req, MAX_UNSFD_MSG_SIZE, -1); fd = open_proc(PROC_SELF, "ns");
if (fd < 0)
return -1;
ret = userns_call(__userns_sysctl_op, UNS_ASYNC, userns_req, MAX_UNSFD_MSG_SIZE, fd);
close(fd);
return ret;
} }
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