rootless: fix an hang on older versions of setresuid/setresgid

the issue is caused by the Go Runtime that messes up with the process
signals, overriding SIGSETXID and SIGCANCEL which are used internally
by glibc.  They are used to inform all the threads to update their
stored uid/gid information.  This causes a hang on the set*id glibc
wrappers since the handler installed by glibc is never invoked.

Since we are running with only one thread, we don't really need to
update other threads or even the current thread as we are not using
getuid/getgid before the execvp.

Closes: https://github.com/containers/libpod/issues/1625

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano
2018-10-11 12:38:10 +02:00
parent 23c9816ba9
commit 48f6f9254d

View File

@ -12,6 +12,18 @@
#include <fcntl.h>
#include <sys/wait.h>
static int
syscall_setresuid (uid_t ruid, uid_t euid, uid_t suid)
{
return (int) syscall (__NR_setresuid, ruid, euid, suid);
}
static int
syscall_setresgid (gid_t rgid, gid_t egid, gid_t sgid)
{
return (int) syscall (__NR_setresgid, rgid, egid, sgid);
}
static int
syscall_clone (unsigned long flags, void *child_stack)
{
@ -107,8 +119,8 @@ reexec_userns_join (int userns)
_exit (EXIT_FAILURE);
close (userns);
if (setresgid (0, 0, 0) < 0 ||
setresuid (0, 0, 0) < 0)
if (syscall_setresgid (0, 0, 0) < 0 ||
syscall_setresuid (0, 0, 0) < 0)
_exit (EXIT_FAILURE);
execvp (argv[0], argv);
@ -146,8 +158,10 @@ reexec_in_user_namespace (int ready)
_exit (EXIT_FAILURE);
close (ready);
if (setresgid (0, 0, 0) < 0 ||
setresuid (0, 0, 0) < 0)
if (syscall_setresgid (0, 0, 0) < 0)
_exit (EXIT_FAILURE);
if (syscall_setresuid (0, 0, 0) < 0)
_exit (EXIT_FAILURE);
execvp (argv[0], argv);