mirror of https://github.com/containers/podman.git
Merge pull request #12325 from giuseppe/rootless-use-auto-cleanup
rootless: use auto cleanup functions
This commit is contained in:
commit
878d22e831
|
@ -19,6 +19,33 @@
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define cleanup_free __attribute__ ((cleanup (cleanup_freep)))
|
||||||
|
#define cleanup_close __attribute__ ((cleanup (cleanup_closep)))
|
||||||
|
#define cleanup_dir __attribute__ ((cleanup (cleanup_dirp)))
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_freep (void *p)
|
||||||
|
{
|
||||||
|
void **pp = (void **) p;
|
||||||
|
free (*pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_closep (void *p)
|
||||||
|
{
|
||||||
|
int *pp = p;
|
||||||
|
if (*pp >= 0)
|
||||||
|
TEMP_FAILURE_RETRY (close (*pp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
cleanup_dirp (DIR **p)
|
||||||
|
{
|
||||||
|
DIR *dir = *p;
|
||||||
|
if (dir)
|
||||||
|
closedir (dir);
|
||||||
|
}
|
||||||
|
|
||||||
int rename_noreplace (int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
|
int rename_noreplace (int olddirfd, const char *oldpath, int newdirfd, const char *newpath)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -119,8 +146,8 @@ do_pause ()
|
||||||
static char **
|
static char **
|
||||||
get_cmd_line_args ()
|
get_cmd_line_args ()
|
||||||
{
|
{
|
||||||
int fd;
|
cleanup_free char *buffer = NULL;
|
||||||
char *buffer;
|
cleanup_close int fd = -1;
|
||||||
size_t allocated;
|
size_t allocated;
|
||||||
size_t used = 0;
|
size_t used = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -139,10 +166,7 @@ get_cmd_line_args ()
|
||||||
{
|
{
|
||||||
ret = TEMP_FAILURE_RETRY (read (fd, buffer + used, allocated - used));
|
ret = TEMP_FAILURE_RETRY (read (fd, buffer + used, allocated - used));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -153,30 +177,21 @@ get_cmd_line_args ()
|
||||||
allocated += 512;
|
allocated += 512;
|
||||||
char *tmp = realloc (buffer, allocated);
|
char *tmp = realloc (buffer, allocated);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
buffer = tmp;
|
buffer = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close (fd);
|
|
||||||
|
|
||||||
for (i = 0; i < used; i++)
|
for (i = 0; i < used; i++)
|
||||||
if (buffer[i] == '\0')
|
if (buffer[i] == '\0')
|
||||||
argc++;
|
argc++;
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
argv = malloc (sizeof (char *) * (argc + 1));
|
argv = malloc (sizeof (char *) * (argc + 1));
|
||||||
if (argv == NULL)
|
if (argv == NULL)
|
||||||
{
|
|
||||||
free (buffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
argc = 0;
|
argc = 0;
|
||||||
|
|
||||||
argv[argc++] = buffer;
|
argv[argc++] = buffer;
|
||||||
|
@ -186,15 +201,19 @@ get_cmd_line_args ()
|
||||||
|
|
||||||
argv[argc] = NULL;
|
argv[argc] = NULL;
|
||||||
|
|
||||||
|
/* Move ownership. */
|
||||||
|
buffer = NULL;
|
||||||
|
|
||||||
return argv;
|
return argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
can_use_shortcut ()
|
can_use_shortcut ()
|
||||||
{
|
{
|
||||||
int argc;
|
cleanup_free char **argv = NULL;
|
||||||
char **argv;
|
cleanup_free char *argv0 = NULL;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
int argc;
|
||||||
|
|
||||||
#ifdef DISABLE_JOIN_SHORTCUT
|
#ifdef DISABLE_JOIN_SHORTCUT
|
||||||
return false;
|
return false;
|
||||||
|
@ -204,12 +223,10 @@ can_use_shortcut ()
|
||||||
if (argv == NULL)
|
if (argv == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
argv0 = argv[0];
|
||||||
|
|
||||||
if (strstr (argv[0], "podman") == NULL)
|
if (strstr (argv[0], "podman") == NULL)
|
||||||
{
|
|
||||||
free (argv[0]);
|
|
||||||
free (argv);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (argc = 0; argv[argc]; argc++)
|
for (argc = 0; argv[argc]; argc++)
|
||||||
{
|
{
|
||||||
|
@ -234,11 +251,25 @@ can_use_shortcut ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (argv[0]);
|
|
||||||
free (argv);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
open_namespace (int pid_to_join, const char *ns_file)
|
||||||
|
{
|
||||||
|
char ns_path[PATH_MAX];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
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");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return open (ns_path, O_CLOEXEC | O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
is_fd_inherited(int fd)
|
is_fd_inherited(int fd)
|
||||||
{
|
{
|
||||||
|
@ -255,8 +286,7 @@ static void __attribute__((constructor)) init()
|
||||||
const char *listen_pid;
|
const char *listen_pid;
|
||||||
const char *listen_fds;
|
const char *listen_fds;
|
||||||
const char *listen_fdnames;
|
const char *listen_fdnames;
|
||||||
|
cleanup_dir DIR *d = NULL;
|
||||||
DIR *d;
|
|
||||||
|
|
||||||
pause = getenv ("_PODMAN_PAUSE");
|
pause = getenv ("_PODMAN_PAUSE");
|
||||||
if (pause && pause[0])
|
if (pause && pause[0])
|
||||||
|
@ -304,7 +334,6 @@ static void __attribute__((constructor)) init()
|
||||||
|
|
||||||
FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE]));
|
FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE]));
|
||||||
}
|
}
|
||||||
closedir (d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listen_pid = getenv("LISTEN_PID");
|
listen_pid = getenv("LISTEN_PID");
|
||||||
|
@ -322,7 +351,7 @@ static void __attribute__((constructor)) init()
|
||||||
if (saved_systemd_listen_pid == NULL
|
if (saved_systemd_listen_pid == NULL
|
||||||
|| saved_systemd_listen_fds == NULL)
|
|| saved_systemd_listen_fds == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "save socket listen environments error: %s\n", strerror (errno));
|
fprintf (stderr, "save socket listen environments error: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,73 +361,70 @@ static void __attribute__((constructor)) init()
|
||||||
xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
|
xdg_runtime_dir = getenv ("XDG_RUNTIME_DIR");
|
||||||
if (geteuid () != 0 && xdg_runtime_dir && xdg_runtime_dir[0] && can_use_shortcut ())
|
if (geteuid () != 0 && xdg_runtime_dir && xdg_runtime_dir[0] && can_use_shortcut ())
|
||||||
{
|
{
|
||||||
int r;
|
cleanup_free char *cwd = NULL;
|
||||||
int fd;
|
cleanup_close int userns_fd = -1;
|
||||||
|
cleanup_close int mntns_fd = -1;
|
||||||
|
cleanup_close int fd = -1;
|
||||||
long pid;
|
long pid;
|
||||||
char buf[12];
|
char buf[12];
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
const char *const suffix = "/libpod/tmp/pause.pid";
|
const char *const suffix = "/libpod/tmp/pause.pid";
|
||||||
char *cwd = getcwd (NULL, 0);
|
|
||||||
char uid_fmt[16];
|
char uid_fmt[16];
|
||||||
char gid_fmt[16];
|
char gid_fmt[16];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
cwd = getcwd (NULL, 0);
|
||||||
if (cwd == NULL)
|
if (cwd == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "error getting current working directory: %s\n", strerror (errno));
|
fprintf (stderr, "error getting current working directory: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = snprintf (path, PATH_MAX, "%s%s", xdg_runtime_dir, suffix);
|
len = snprintf (path, PATH_MAX, "%s%s", xdg_runtime_dir, suffix);
|
||||||
if (len >= PATH_MAX)
|
if (len >= PATH_MAX)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "invalid value for XDG_RUNTIME_DIR: %s", strerror (ENAMETOOLONG));
|
errno = ENAMETOOLONG;
|
||||||
|
fprintf (stderr, "invalid value for XDG_RUNTIME_DIR: %m");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open (path, O_RDONLY);
|
fd = open (path, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
|
||||||
free (cwd);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf) - 1));
|
r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf) - 1));
|
||||||
close (fd);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
|
||||||
free (cwd);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
buf[r] = '\0';
|
buf[r] = '\0';
|
||||||
|
|
||||||
pid = strtol (buf, NULL, 10);
|
pid = strtol (buf, NULL, 10);
|
||||||
if (pid == LONG_MAX)
|
if (pid == LONG_MAX)
|
||||||
{
|
|
||||||
free (cwd);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
uid = geteuid ();
|
uid = geteuid ();
|
||||||
gid = getegid ();
|
gid = getegid ();
|
||||||
|
|
||||||
sprintf (path, "/proc/%ld/ns/user", pid);
|
userns_fd = open_namespace (pid, "user");
|
||||||
fd = open (path, O_RDONLY);
|
if (userns_fd < 0)
|
||||||
if (fd < 0 || setns (fd, 0) < 0)
|
|
||||||
{
|
|
||||||
free (cwd);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
|
|
||||||
/* Errors here cannot be ignored as we already joined a ns. */
|
mntns_fd = open_namespace (pid, "mnt");
|
||||||
sprintf (path, "/proc/%ld/ns/mnt", pid);
|
if (mntns_fd < 0)
|
||||||
fd = open (path, O_RDONLY);
|
return;
|
||||||
if (fd < 0)
|
|
||||||
|
if (setns (userns_fd, 0) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* The user namespace was joined, after this point errors are
|
||||||
|
not recoverable anymore. */
|
||||||
|
|
||||||
|
if (setns (mntns_fd, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot open %s: %s", path, strerror (errno));
|
fprintf (stderr, "cannot join mount namespace for %ld: %m", pid);
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,33 +435,24 @@ static void __attribute__((constructor)) init()
|
||||||
setenv ("_CONTAINERS_ROOTLESS_UID", uid_fmt, 1);
|
setenv ("_CONTAINERS_ROOTLESS_UID", uid_fmt, 1);
|
||||||
setenv ("_CONTAINERS_ROOTLESS_GID", gid_fmt, 1);
|
setenv ("_CONTAINERS_ROOTLESS_GID", gid_fmt, 1);
|
||||||
|
|
||||||
r = setns (fd, 0);
|
|
||||||
if (r < 0)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "cannot join mount namespace for %ld: %s", pid, strerror (errno));
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
close (fd);
|
|
||||||
|
|
||||||
if (syscall_setresgid (0, 0, 0) < 0)
|
if (syscall_setresgid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresgid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresgid: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syscall_setresuid (0, 0, 0) < 0)
|
if (syscall_setresuid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresuid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresuid: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chdir (cwd) < 0)
|
if (chdir (cwd) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot chdir to %s: %s\n", cwd, strerror (errno));
|
fprintf (stderr, "cannot chdir to %s: %m\n", cwd);
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (cwd);
|
|
||||||
rootless_uid_init = uid;
|
rootless_uid_init = uid;
|
||||||
rootless_gid_init = gid;
|
rootless_gid_init = gid;
|
||||||
}
|
}
|
||||||
|
@ -534,7 +551,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
|
||||||
fd = mkstemp (tmp_file_path);
|
fd = mkstemp (tmp_file_path);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "error creating temporary file: %s\n", strerror (errno));
|
fprintf (stderr, "error creating temporary file: %m\n");
|
||||||
kill (pid, SIGKILL);
|
kill (pid, SIGKILL);
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -542,7 +559,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
|
||||||
r = TEMP_FAILURE_RETRY (write (fd, pid_str, strlen (pid_str)));
|
r = TEMP_FAILURE_RETRY (write (fd, pid_str, strlen (pid_str)));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot write to file descriptor: %s\n", strerror (errno));
|
fprintf (stderr, "cannot write to file descriptor: %m\n");
|
||||||
kill (pid, SIGKILL);
|
kill (pid, SIGKILL);
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -560,7 +577,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
|
||||||
r = TEMP_FAILURE_RETRY (write (p[1], "0", 1));
|
r = TEMP_FAILURE_RETRY (write (p[1], "0", 1));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot write to pipe: %s\n", strerror (errno));
|
fprintf (stderr, "cannot write to pipe: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
close (p[1]);
|
close (p[1]);
|
||||||
|
@ -595,22 +612,6 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
open_namespace (int pid_to_join, const char *ns_file)
|
|
||||||
{
|
|
||||||
char ns_path[PATH_MAX];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
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");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return open (ns_path, O_CLOEXEC | O_RDONLY);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
join_namespace_or_die (const char *name, int ns_fd)
|
join_namespace_or_die (const char *name, int ns_fd)
|
||||||
{
|
{
|
||||||
|
@ -624,18 +625,20 @@ join_namespace_or_die (const char *name, int ns_fd)
|
||||||
int
|
int
|
||||||
reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
||||||
{
|
{
|
||||||
|
cleanup_close int userns_fd = -1;
|
||||||
|
cleanup_close int mntns_fd = -1;
|
||||||
|
cleanup_free char *cwd = NULL;
|
||||||
char uid[16];
|
char uid[16];
|
||||||
char gid[16];
|
char gid[16];
|
||||||
char **argv;
|
cleanup_free char *argv0 = NULL;
|
||||||
|
cleanup_free char **argv = NULL;
|
||||||
int pid;
|
int pid;
|
||||||
int mnt_ns = -1;
|
|
||||||
int user_ns = -1;
|
|
||||||
char *cwd = getcwd (NULL, 0);
|
|
||||||
sigset_t sigset, oldsigset;
|
sigset_t sigset, oldsigset;
|
||||||
|
|
||||||
|
cwd = getcwd (NULL, 0);
|
||||||
if (cwd == NULL)
|
if (cwd == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "error getting current working directory: %s\n", strerror (errno));
|
fprintf (stderr, "error getting current working directory: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,32 +648,27 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
||||||
argv = get_cmd_line_args ();
|
argv = get_cmd_line_args ();
|
||||||
if (argv == NULL)
|
if (argv == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot read argv: %s\n", strerror (errno));
|
fprintf (stderr, "cannot read argv: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
user_ns = open_namespace (pid_to_join, "user");
|
argv0 = argv[0];
|
||||||
if (user_ns < 0)
|
|
||||||
return user_ns;
|
userns_fd = open_namespace (pid_to_join, "user");
|
||||||
mnt_ns = open_namespace (pid_to_join, "mnt");
|
if (userns_fd < 0)
|
||||||
if (mnt_ns < 0)
|
return userns_fd;
|
||||||
{
|
mntns_fd = open_namespace (pid_to_join, "mnt");
|
||||||
close (user_ns);
|
if (mntns_fd < 0)
|
||||||
return mnt_ns;
|
return mntns_fd;
|
||||||
}
|
|
||||||
|
|
||||||
pid = fork ();
|
pid = fork ();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
fprintf (stderr, "cannot fork: %s\n", strerror (errno));
|
fprintf (stderr, "cannot fork: %m\n");
|
||||||
|
|
||||||
if (pid)
|
if (pid)
|
||||||
{
|
{
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
/* We passed down these fds, close them. */
|
|
||||||
close (user_ns);
|
|
||||||
close (mnt_ns);
|
|
||||||
|
|
||||||
for (f = 3; f <= open_files_max_fd; f++)
|
for (f = 3; f <= open_files_max_fd; f++)
|
||||||
if (is_fd_inherited (f))
|
if (is_fd_inherited (f))
|
||||||
close (f);
|
close (f);
|
||||||
|
@ -686,22 +684,22 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
||||||
|
|
||||||
if (sigfillset (&sigset) < 0)
|
if (sigfillset (&sigset) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot fill sigset: %s\n", strerror (errno));
|
fprintf (stderr, "cannot fill sigset: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigdelset (&sigset, SIGCHLD) < 0)
|
if (sigdelset (&sigset, SIGCHLD) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot sigdelset(SIGCHLD): %s\n", strerror (errno));
|
fprintf (stderr, "cannot sigdelset(SIGCHLD): %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigdelset (&sigset, SIGTERM) < 0)
|
if (sigdelset (&sigset, SIGTERM) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot sigdelset(SIGTERM): %s\n", strerror (errno));
|
fprintf (stderr, "cannot sigdelset(SIGTERM): %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigprocmask (SIG_BLOCK, &sigset, &oldsigset) < 0)
|
if (sigprocmask (SIG_BLOCK, &sigset, &oldsigset) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
|
fprintf (stderr, "cannot block signals: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,33 +720,30 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
||||||
|
|
||||||
if (prctl (PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) < 0)
|
if (prctl (PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot prctl(PR_SET_PDEATHSIG): %s\n", strerror (errno));
|
fprintf (stderr, "cannot prctl(PR_SET_PDEATHSIG): %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
join_namespace_or_die ("user", user_ns);
|
join_namespace_or_die ("user", userns_fd);
|
||||||
join_namespace_or_die ("mnt", mnt_ns);
|
join_namespace_or_die ("mnt", mntns_fd);
|
||||||
close (user_ns);
|
|
||||||
close (mnt_ns);
|
|
||||||
|
|
||||||
if (syscall_setresgid (0, 0, 0) < 0)
|
if (syscall_setresgid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresgid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresgid: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syscall_setresuid (0, 0, 0) < 0)
|
if (syscall_setresuid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresuid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresuid: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chdir (cwd) < 0)
|
if (chdir (cwd) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot chdir to %s: %s\n", cwd, strerror (errno));
|
fprintf (stderr, "cannot chdir to %s: %m\n", cwd);
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
free (cwd);
|
|
||||||
|
|
||||||
if (pause_pid_file_path && pause_pid_file_path[0] != '\0')
|
if (pause_pid_file_path && pause_pid_file_path[0] != '\0')
|
||||||
{
|
{
|
||||||
|
@ -757,7 +752,7 @@ reexec_userns_join (int pid_to_join, char *pause_pid_file_path)
|
||||||
}
|
}
|
||||||
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
|
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
|
fprintf (stderr, "cannot block signals: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,7 +784,7 @@ static int
|
||||||
copy_file_to_fd (const char *file_to_read, int outfd)
|
copy_file_to_fd (const char *file_to_read, int outfd)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
int fd;
|
cleanup_close int fd = -1;
|
||||||
|
|
||||||
fd = open (file_to_read, O_RDONLY);
|
fd = open (file_to_read, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
@ -801,10 +796,7 @@ copy_file_to_fd (const char *file_to_read, int outfd)
|
||||||
|
|
||||||
r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof buf));
|
r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof buf));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
{
|
|
||||||
close (fd);
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
|
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -813,43 +805,40 @@ copy_file_to_fd (const char *file_to_read, int outfd)
|
||||||
{
|
{
|
||||||
w = TEMP_FAILURE_RETRY (write (outfd, &buf[t], r - t));
|
w = TEMP_FAILURE_RETRY (write (outfd, &buf[t], r - t));
|
||||||
if (w < 0)
|
if (w < 0)
|
||||||
{
|
|
||||||
close (fd);
|
|
||||||
return w;
|
return w;
|
||||||
}
|
|
||||||
t += w;
|
t += w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close (fd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_read, int outputfd)
|
reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_read, int outputfd)
|
||||||
{
|
{
|
||||||
|
cleanup_free char **argv = NULL;
|
||||||
|
cleanup_free char *argv0 = NULL;
|
||||||
|
cleanup_free char *cwd = NULL;
|
||||||
|
sigset_t sigset, oldsigset;
|
||||||
int ret;
|
int ret;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char b;
|
char b;
|
||||||
char **argv;
|
|
||||||
char uid[16];
|
char uid[16];
|
||||||
char gid[16];
|
char gid[16];
|
||||||
char *cwd = getcwd (NULL, 0);
|
|
||||||
sigset_t sigset, oldsigset;
|
|
||||||
|
|
||||||
|
cwd = getcwd (NULL, 0);
|
||||||
if (cwd == NULL)
|
if (cwd == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "error getting current working directory: %s\n", strerror (errno));
|
fprintf (stderr, "error getting current working directory: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sprintf (uid, "%d", geteuid ());
|
sprintf (uid, "%d", geteuid ());
|
||||||
sprintf (gid, "%d", getegid ());
|
sprintf (gid, "%d", getegid ());
|
||||||
|
|
||||||
pid = syscall_clone (CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
|
pid = syscall_clone (CLONE_NEWUSER|CLONE_NEWNS|SIGCHLD, NULL);
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot clone: %s\n", strerror (errno));
|
fprintf (stderr, "cannot clone: %m\n");
|
||||||
check_proc_sys_userns_file (_max_user_namespaces);
|
check_proc_sys_userns_file (_max_user_namespaces);
|
||||||
check_proc_sys_userns_file (_unprivileged_user_namespaces);
|
check_proc_sys_userns_file (_unprivileged_user_namespaces);
|
||||||
}
|
}
|
||||||
|
@ -877,32 +866,34 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
||||||
|
|
||||||
if (sigfillset (&sigset) < 0)
|
if (sigfillset (&sigset) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot fill sigset: %s\n", strerror (errno));
|
fprintf (stderr, "cannot fill sigset: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigdelset (&sigset, SIGCHLD) < 0)
|
if (sigdelset (&sigset, SIGCHLD) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot sigdelset(SIGCHLD): %s\n", strerror (errno));
|
fprintf (stderr, "cannot sigdelset(SIGCHLD): %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigdelset (&sigset, SIGTERM) < 0)
|
if (sigdelset (&sigset, SIGTERM) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot sigdelset(SIGTERM): %s\n", strerror (errno));
|
fprintf (stderr, "cannot sigdelset(SIGTERM): %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (sigprocmask (SIG_BLOCK, &sigset, &oldsigset) < 0)
|
if (sigprocmask (SIG_BLOCK, &sigset, &oldsigset) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
|
fprintf (stderr, "cannot block signals: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
argv = get_cmd_line_args ();
|
argv = get_cmd_line_args ();
|
||||||
if (argv == NULL)
|
if (argv == NULL)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot read argv: %s\n", strerror (errno));
|
fprintf (stderr, "cannot read argv: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
argv0 = argv[0];
|
||||||
|
|
||||||
if (do_socket_activation)
|
if (do_socket_activation)
|
||||||
{
|
{
|
||||||
char s[32];
|
char s[32];
|
||||||
|
@ -921,7 +912,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
||||||
ret = TEMP_FAILURE_RETRY (read (ready, &b, 1));
|
ret = TEMP_FAILURE_RETRY (read (ready, &b, 1));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot read from sync pipe: %s\n", strerror (errno));
|
fprintf (stderr, "cannot read from sync pipe: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (ret != 1 || b != '0')
|
if (ret != 1 || b != '0')
|
||||||
|
@ -929,25 +920,24 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
||||||
|
|
||||||
if (syscall_setresgid (0, 0, 0) < 0)
|
if (syscall_setresgid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresgid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresgid: %m\n");
|
||||||
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (syscall_setresuid (0, 0, 0) < 0)
|
if (syscall_setresuid (0, 0, 0) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot setresuid: %s\n", strerror (errno));
|
fprintf (stderr, "cannot setresuid: %m\n");
|
||||||
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chdir (cwd) < 0)
|
if (chdir (cwd) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot chdir to %s: %s\n", cwd, strerror (errno));
|
fprintf (stderr, "cannot chdir to %s: %m\n", cwd);
|
||||||
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
TEMP_FAILURE_RETRY (write (ready, "1", 1));
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
free (cwd);
|
|
||||||
|
|
||||||
if (pause_pid_file_path && pause_pid_file_path[0] != '\0')
|
if (pause_pid_file_path && pause_pid_file_path[0] != '\0')
|
||||||
{
|
{
|
||||||
|
@ -961,14 +951,14 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
|
||||||
ret = TEMP_FAILURE_RETRY (write (ready, "0", 1));
|
ret = TEMP_FAILURE_RETRY (write (ready, "0", 1));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot write to ready pipe: %s\n", strerror (errno));
|
fprintf (stderr, "cannot write to ready pipe: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
close (ready);
|
close (ready);
|
||||||
|
|
||||||
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
|
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "cannot block signals: %s\n", strerror (errno));
|
fprintf (stderr, "cannot block signals: %m\n");
|
||||||
_exit (EXIT_FAILURE);
|
_exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue