Merge pull request #5323 from giuseppe/rootless-join-fixes

rootless: fix segfault when open fd >= FD_SETSIZE
This commit is contained in:
OpenShift Merge Robot 2020-02-25 21:16:19 +01:00 committed by GitHub
commit 72fdccda7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 36 additions and 15 deletions

View File

@ -58,7 +58,7 @@ 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 const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
static int open_files_max_fd; static int open_files_max_fd;
fd_set open_files_set; static fd_set *open_files_set;
static uid_t rootless_uid_init; static uid_t rootless_uid_init;
static gid_t rootless_gid_init; static gid_t rootless_gid_init;
@ -240,17 +240,39 @@ static void __attribute__((constructor)) init()
if (d) if (d)
{ {
struct dirent *ent; struct dirent *ent;
size_t size = 0;
FD_ZERO (&open_files_set);
for (ent = readdir (d); ent; ent = readdir (d)) for (ent = readdir (d); ent; ent = readdir (d))
{ {
int fd = atoi (ent->d_name); int fd;
if (fd != dirfd (d))
if (ent->d_name[0] == '.')
continue;
fd = atoi (ent->d_name);
if (fd == dirfd (d))
continue;
if (fd >= size * FD_SETSIZE)
{ {
if (fd > open_files_max_fd) int i;
open_files_max_fd = fd; size_t new_size;
FD_SET (fd, &open_files_set);
new_size = (fd / FD_SETSIZE) + 1;
open_files_set = realloc (open_files_set, new_size * sizeof (fd_set));
if (open_files_set == NULL)
_exit (EXIT_FAILURE);
for (i = size; i < new_size; i++)
FD_ZERO (&(open_files_set[i]));
size = new_size;
} }
if (fd > open_files_max_fd)
open_files_max_fd = fd;
FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE]));
} }
closedir (d); closedir (d);
} }
@ -553,10 +575,8 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path)
/* We passed down these fds, close them. */ /* We passed down these fds, close them. */
int f; int f;
for (f = 3; f < open_files_max_fd; f++) for (f = 3; f < open_files_max_fd; f++)
{ if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
if (FD_ISSET (f, &open_files_set)) close (f);
close (f);
}
return pid; return pid;
} }
@ -747,10 +767,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
num_fds = strtol (listen_fds, NULL, 10); num_fds = strtol (listen_fds, NULL, 10);
if (num_fds != LONG_MIN && num_fds != LONG_MAX) if (num_fds != LONG_MIN && num_fds != LONG_MAX)
{ {
long i; int f;
for (i = 3; i < num_fds + 3; i++)
if (FD_ISSET (i, &open_files_set)) for (f = 3; f < num_fds + 3; f++)
close (i); if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
close (f);
} }
unsetenv ("LISTEN_PID"); unsetenv ("LISTEN_PID");
unsetenv ("LISTEN_FDS"); unsetenv ("LISTEN_FDS");