start: use CLONE_PIDFD

Use CLONE_PIDFD when possible. Note the clone() syscall ignores unknown flags which is usually a design mistake. However, for us this bug is a feature since we can just pass the flag along and see whether the kernel has given us a pidfd. Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 33258b95
...@@ -406,7 +406,9 @@ static int signal_handler(int fd, uint32_t events, void *data, ...@@ -406,7 +406,9 @@ static int signal_handler(int fd, uint32_t events, void *data,
} }
if (siginfo.ssi_signo == SIGHUP) { if (siginfo.ssi_signo == SIGHUP) {
if (hdlr->proc_pidfd >= 0) if (hdlr->pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->pidfd, SIGTERM, NULL, 0);
else if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, SIGTERM, NULL, 0); lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, SIGTERM, NULL, 0);
else else
kill(hdlr->pid, SIGTERM); kill(hdlr->pid, SIGTERM);
...@@ -416,7 +418,10 @@ static int signal_handler(int fd, uint32_t events, void *data, ...@@ -416,7 +418,10 @@ static int signal_handler(int fd, uint32_t events, void *data,
} }
if (siginfo.ssi_signo != SIGCHLD) { if (siginfo.ssi_signo != SIGCHLD) {
if (hdlr->proc_pidfd >= 0) if (hdlr->pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->pidfd,
siginfo.ssi_signo, NULL, 0);
else if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, lxc_raw_pidfd_send_signal(hdlr->proc_pidfd,
siginfo.ssi_signo, NULL, 0); siginfo.ssi_signo, NULL, 0);
else else
...@@ -665,6 +670,8 @@ void lxc_zero_handler(struct lxc_handler *handler) ...@@ -665,6 +670,8 @@ void lxc_zero_handler(struct lxc_handler *handler)
handler->pinfd = -1; handler->pinfd = -1;
handler->pidfd = -EBADF;
handler->proc_pidfd = -EBADF; handler->proc_pidfd = -EBADF;
handler->sigfd = -1; handler->sigfd = -1;
...@@ -687,6 +694,9 @@ void lxc_free_handler(struct lxc_handler *handler) ...@@ -687,6 +694,9 @@ void lxc_free_handler(struct lxc_handler *handler)
if (handler->pinfd >= 0) if (handler->pinfd >= 0)
close(handler->pinfd); close(handler->pinfd);
if (handler->pidfd >= 0)
close(handler->pidfd);
if (handler->proc_pidfd >= 0) if (handler->proc_pidfd >= 0)
close(handler->proc_pidfd); close(handler->proc_pidfd);
...@@ -734,6 +744,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, ...@@ -734,6 +744,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
handler->conf = conf; handler->conf = conf;
handler->lxcpath = lxcpath; handler->lxcpath = lxcpath;
handler->pinfd = -1; handler->pinfd = -1;
handler->pidfd = -EBADF;
handler->proc_pidfd = -EBADF; handler->proc_pidfd = -EBADF;
handler->sigfd = -EBADF; handler->sigfd = -EBADF;
handler->init_died = false; handler->init_died = false;
...@@ -1096,19 +1107,23 @@ void lxc_fini(const char *name, struct lxc_handler *handler) ...@@ -1096,19 +1107,23 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
void lxc_abort(const char *name, struct lxc_handler *handler) void lxc_abort(const char *name, struct lxc_handler *handler)
{ {
int ret, status; int ret = 0;
int status;
lxc_set_state(name, handler, ABORTING); lxc_set_state(name, handler, ABORTING);
if (handler->pid > 0) { if (handler->pidfd > 0)
ret = lxc_raw_pidfd_send_signal(handler->pidfd, SIGKILL, NULL, 0);
else if (handler->proc_pidfd > 0)
ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0); ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0);
else if (handler->pid > 0)
ret = kill(handler->pid, SIGKILL);
if (ret < 0) if (ret < 0)
SYSERROR("Failed to send SIGKILL to %d", handler->pid); SYSERROR("Failed to send SIGKILL to %d", handler->pid);
}
while ((ret = waitpid(-1, &status, 0)) > 0) { do {
; ret = waitpid(-1, &status, 0);
} } while (ret > 0);
} }
static int do_start(void *data) static int do_start(void *data)
...@@ -1601,7 +1616,8 @@ static inline int do_share_ns(void *arg) ...@@ -1601,7 +1616,8 @@ static inline int do_share_ns(void *arg)
flags = handler->ns_on_clone_flags; flags = handler->ns_on_clone_flags;
flags |= CLONE_PARENT; flags |= CLONE_PARENT;
handler->pid = lxc_raw_clone_cb(do_start, handler, flags, NULL); handler->pid = lxc_raw_clone_cb(do_start, handler, CLONE_PIDFD | flags,
&handler->pidfd);
if (handler->pid < 0) if (handler->pid < 0)
return -1; return -1;
...@@ -1748,7 +1764,8 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1748,7 +1764,8 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
} else { } else {
handler->pid = lxc_raw_clone_cb(do_start, handler, handler->pid = lxc_raw_clone_cb(do_start, handler,
handler->ns_on_clone_flags, NULL); CLONE_PIDFD | handler->ns_on_clone_flags,
&handler->pidfd);
} }
if (handler->pid < 0) { if (handler->pid < 0) {
SYSERROR(LXC_CLONE_ERROR); SYSERROR(LXC_CLONE_ERROR);
...@@ -1756,9 +1773,11 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1756,9 +1773,11 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
TRACE("Cloned child process %d", handler->pid); TRACE("Cloned child process %d", handler->pid);
if (handler->pidfd < 0) {
handler->proc_pidfd = proc_pidfd_open(handler->pid); handler->proc_pidfd = proc_pidfd_open(handler->pid);
if (handler->proc_pidfd < 0 && (errno != ENOSYS)) if (handler->proc_pidfd < 0 && (errno != ENOSYS))
goto out_delete_net; goto out_delete_net;
}
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag) if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
......
...@@ -102,6 +102,9 @@ struct lxc_handler { ...@@ -102,6 +102,9 @@ struct lxc_handler {
/* The child's pid. */ /* The child's pid. */
pid_t pid; pid_t pid;
/* The child's pidfd. */
int pidfd;
/* /*
* File descriptor for the /proc/<pid> directory of the container's * File descriptor for the /proc/<pid> directory of the container's
* init process. * init process.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment