From 912314fc9b63e8cffaf3d5160f9171fc6a0805d4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 22 Dec 2017 22:17:44 +0100 Subject: [PATCH 1/2] start: fix death signal On set{g,u}id() the kernel does: /* dumpability changes */ if (!uid_eq(old->euid, new->euid) || !gid_eq(old->egid, new->egid) || !uid_eq(old->fsuid, new->fsuid) || !gid_eq(old->fsgid, new->fsgid) || !cred_cap_issubset(old, new)) { if (task->mm) set_dumpable(task->mm, suid_dumpable); task->pdeath_signal = 0; smp_wmb(); } which means we need to re-enable the deat signal after the set{g,u}id(). Signed-off-by: Christian Brauner --- src/lxc/start.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index c7d87fb3c..2b09d89ab 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -888,8 +888,9 @@ static int do_start(void *data) * exit before we set the pdeath signal leading to a unsupervized * container. */ - if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) { - SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL."); + ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + if (ret < 0) { + SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL"); return -1; } @@ -946,6 +947,13 @@ static int do_start(void *data) if (ret < 0) goto out_warn_father; } + + /* set{g,u}id() clears deathsignal */ + ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + if (ret < 0) { + SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL"); + goto out_warn_father; + } } if (access(handler->lxcpath, X_OK)) { From 18225d1985247a8df08d25d07b0797525847d502 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 22 Dec 2017 22:52:42 +0100 Subject: [PATCH 2/2] start: handle setting death signal smarter Signed-off-by: Christian Brauner --- src/lxc/start.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index 2b09d89ab..d70764fa1 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -866,6 +866,32 @@ void lxc_abort(const char *name, struct lxc_handler *handler) } } +static int lxc_set_death_signal(int signal) +{ + int ret; + pid_t ppid; + + ret = prctl(PR_SET_PDEATHSIG, signal, 0, 0, 0); + + /* Check whether we have been orphaned. */ + ppid = (pid_t)syscall(SYS_getppid); + if (ppid == 1) { + pid_t self; + + self = lxc_raw_getpid(); + ret = kill(self, SIGKILL); + if (ret < 0) + return -1; + } + + if (ret < 0) { + SYSERROR("Failed to set PR_SET_PDEATHSIG to %d", signal); + return -1; + } + + return 0; +} + static int do_start(void *data) { int ret; @@ -877,10 +903,7 @@ static int do_start(void *data) gid_t new_gid; int devnull_fd = -1; - if (sigprocmask(SIG_SETMASK, &handler->oldmask, NULL)) { - SYSERROR("Failed to set signal mask."); - return -1; - } + lxc_sync_fini_parent(handler); /* This prctl must be before the synchro, so if the parent dies before * we set the parent death signal, we will detect its death with the @@ -888,20 +911,25 @@ static int do_start(void *data) * exit before we set the pdeath signal leading to a unsupervized * container. */ - ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + ret = lxc_set_death_signal(SIGKILL); if (ret < 0) { SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL"); - return -1; + goto out_warn_father; } - lxc_sync_fini_parent(handler); + ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL); + if (ret < 0) { + SYSERROR("Failed to set signal mask"); + goto out_warn_father; + } /* Don't leak the pinfd to the container. */ if (handler->pinfd >= 0) close(handler->pinfd); - if (lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP)) - return -1; + ret = lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP); + if (ret < 0) + goto out_warn_father; /* Unshare CLONE_NEWNET after CLONE_NEWUSER. See * https://github.com/lxc/lxd/issues/1978. @@ -949,7 +977,7 @@ static int do_start(void *data) } /* set{g,u}id() clears deathsignal */ - ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); + ret = lxc_set_death_signal(SIGKILL); if (ret < 0) { SYSERROR("Failed to set PR_SET_PDEATHSIG to SIGKILL"); goto out_warn_father; @@ -1425,7 +1453,6 @@ static int lxc_spawn(struct lxc_handler *handler) SYSERROR(LXC_CLONE_ERROR); goto out_delete_net; } - TRACE("Cloned child process %d", handler->pid); for (i = 0; i < LXC_NS_MAX; i++)