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 int open_files_max_fd;
fd_set open_files_set;
static fd_set *open_files_set;
static uid_t rootless_uid_init;
static gid_t rootless_gid_init;
@ -240,17 +240,39 @@ static void __attribute__((constructor)) init()
if (d)
{
struct dirent *ent;
size_t size = 0;
FD_ZERO (&open_files_set);
for (ent = readdir (d); ent; ent = readdir (d))
{
int fd = atoi (ent->d_name);
if (fd != dirfd (d))
int fd;
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)
open_files_max_fd = fd;
FD_SET (fd, &open_files_set);
int i;
size_t new_size;
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);
}
@ -553,10 +575,8 @@ reexec_userns_join (int userns, int mountns, char *pause_pid_file_path)
/* We passed down these fds, close them. */
int f;
for (f = 3; f < open_files_max_fd; f++)
{
if (FD_ISSET (f, &open_files_set))
close (f);
}
if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
close (f);
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);
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);
int f;
for (f = 3; f < num_fds + 3; f++)
if (open_files_set == NULL || FD_ISSET (f % FD_SETSIZE, &(open_files_set[f / FD_SETSIZE])))
close (f);
}
unsetenv ("LISTEN_PID");
unsetenv ("LISTEN_FDS");