From 788fdc685b00dee5ccb594bef845204250c4c123 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Mon, 20 Apr 2020 12:02:53 +0200 Subject: rootless: move join namespace inside child process open the namespace file descriptors inside of the child process. Closes: https://github.com/containers/libpod/issues/5873 Signed-off-by: Giuseppe Scrivano --- pkg/rootless/rootless_linux.c | 45 +++++++++++++++++++++++++++++------------- pkg/rootless/rootless_linux.go | 24 ++-------------------- 2 files changed, 33 insertions(+), 36 deletions(-) (limited to 'pkg') diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index da52a7217..72d461cdc 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -535,8 +535,36 @@ create_pause_process (const char *pause_pid_file_path, char **argv) } } +static void +join_namespace_or_die (int pid_to_join, const char *ns_file) +{ + char ns_path[PATH_MAX]; + int ret; + int fd; + + ret = snprintf (ns_path, PATH_MAX, "/proc/%d/ns/%s", pid_to_join, ns_file); + if (ret == PATH_MAX) + { + fprintf (stderr, "internal error: namespace path too long\n"); + _exit (EXIT_FAILURE); + } + + fd = open (ns_path, O_CLOEXEC | O_RDONLY); + if (fd < 0) + { + fprintf (stderr, "cannot open: %s\n", ns_path); + _exit (EXIT_FAILURE); + } + if (setns (fd, 0) < 0) + { + fprintf (stderr, "cannot set namespace to %s: %s\n", ns_path, strerror (errno)); + _exit (EXIT_FAILURE); + } + close (fd); +} + int -reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) +reexec_userns_join (int pid_to_join, char *pause_pid_file_path) { char uid[16]; char gid[16]; @@ -606,19 +634,8 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path) _exit (EXIT_FAILURE); } - if (setns (userns, 0) < 0) - { - fprintf (stderr, "cannot setns: %s\n", strerror (errno)); - _exit (EXIT_FAILURE); - } - close (userns); - - if (mountns >= 0 && setns (mountns, 0) < 0) - { - fprintf (stderr, "cannot setns: %s\n", strerror (errno)); - _exit (EXIT_FAILURE); - } - close (mountns); + join_namespace_or_die (pid_to_join, "user"); + join_namespace_or_die (pid_to_join, "mnt"); if (syscall_setresgid (0, 0, 0) < 0) { diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index f01ebe5fc..3de136f12 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -31,7 +31,7 @@ extern uid_t rootless_uid(); extern uid_t rootless_gid(); extern int reexec_in_user_namespace(int ready, char *pause_pid_file_path, char *file_to_read, int fd); extern int reexec_in_user_namespace_wait(int pid, int options); -extern int reexec_userns_join(int userns, int mountns, char *pause_pid_file_path); +extern int reexec_userns_join(int pid, char *pause_pid_file_path); */ import "C" @@ -135,27 +135,7 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) { cPausePid := C.CString(pausePid) defer C.free(unsafe.Pointer(cPausePid)) - userNS, err := os.Open(fmt.Sprintf("/proc/%d/ns/user", pid)) - if err != nil { - return false, -1, err - } - defer func() { - if err := userNS.Close(); err != nil { - logrus.Errorf("unable to close namespace: %q", err) - } - }() - - mountNS, err := os.Open(fmt.Sprintf("/proc/%d/ns/mnt", pid)) - if err != nil { - return false, -1, err - } - defer func() { - if err := mountNS.Close(); err != nil { - logrus.Errorf("unable to close namespace: %q", err) - } - }() - - pidC := C.reexec_userns_join(C.int(userNS.Fd()), C.int(mountNS.Fd()), cPausePid) + pidC := C.reexec_userns_join(C.int(pid), cPausePid) if int(pidC) < 0 { return false, -1, errors.Errorf("cannot re-exec process") } -- cgit v1.2.3-54-g00ecf