From 0dfb61d8064feaae1ac83fcfb15514c30cb8ca28 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 18 Apr 2019 10:27:08 +0200 Subject: rootless: not close more FDs than needed we were previously closing as many FDs as they were open when we first started Podman in the range (3-MAX-FD). This would cause issues if there were empty intervals, as these FDs are later on used by the Golang runtime. Store exactly what FDs were first open in a fd_set, so that we can close exactly the FDs that were open at startup. Closes: https://github.com/containers/libpod/issues/2964 Signed-off-by: Giuseppe Scrivano --- pkg/rootless/rootless_linux.c | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'pkg') diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 9cb79ed4d..1d32b1adb 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -16,11 +16,13 @@ #include #include #include +#include static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone"; -static int n_files; +static int open_files_max_fd; +fd_set open_files_set; static void __attribute__((constructor)) init() { @@ -32,11 +34,16 @@ static void __attribute__((constructor)) init() { struct dirent *ent; + FD_ZERO (&open_files_set); for (ent = readdir (d); ent; ent = readdir (d)) { int fd = atoi (ent->d_name); - if (fd > n_files && fd != dirfd (d)) - n_files = fd; + if (fd != dirfd (d)) + { + if (fd > open_files_max_fd) + open_files_max_fd = fd; + FD_SET (fd, &open_files_set); + } } closedir (d); } @@ -164,8 +171,11 @@ reexec_userns_join (int userns, int mountns) { /* We passed down these fds, close them. */ int f; - for (f = 3; f < n_files; f++) - close (f); + for (f = 3; f < open_files_max_fd; f++) + { + if (FD_ISSET (f, &open_files_set)) + close (f); + } return pid; } @@ -274,22 +284,25 @@ reexec_in_user_namespace (int ready) check_proc_sys_userns_file (_max_user_namespaces); check_proc_sys_userns_file (_unprivileged_user_namespaces); } - if (pid) { - if (do_socket_activation) { - long num_fds; - num_fds = strtol(listen_fds, NULL, 10); - if (num_fds != LONG_MIN && num_fds != LONG_MAX) { - long i; - for (i = 0; i < num_fds; i++) { - close(3+i); + if (pid) + { + if (do_socket_activation) + { + long num_fds; + num_fds = strtol (listen_fds, NULL, 10); + if (num_fds != LONG_MIN && num_fds != LONG_MAX) + { + long i; + for (i = 3; i < num_fds + 3; i++) + if (FD_ISSET (i, &open_files_set)) + close (i); + } + unsetenv ("LISTEN_PID"); + unsetenv ("LISTEN_FDS"); + unsetenv ("LISTEN_FDNAMES"); } - } - unsetenv("LISTEN_PID"); - unsetenv("LISTEN_FDS"); - unsetenv("LISTEN_FDNAMES"); + return pid; } - return pid; - } argv = get_cmd_line_args (ppid); if (argv == NULL) @@ -300,8 +313,8 @@ reexec_in_user_namespace (int ready) if (do_socket_activation) { char s[32]; - sprintf(s, "%d", getpid()); - setenv("LISTEN_PID", s, true); + sprintf (s, "%d", getpid()); + setenv ("LISTEN_PID", s, true); } setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1); -- cgit v1.2.3-54-g00ecf