diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 2515c881e..0fbbbfa79 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -4419,7 +4419,7 @@ int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), void *data, d.p[1] = p[1]; /* Clone child in new user namespace. */ - pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER); + pid = lxc_clone(run_userns_fn, &d, CLONE_NEWUSER, NULL); if (pid < 0) { ERROR("Failed to clone process in new user namespace"); goto on_error; diff --git a/src/lxc/namespace.c b/src/lxc/namespace.c index e22d9a4bf..59fba412d 100644 --- a/src/lxc/namespace.c +++ b/src/lxc/namespace.c @@ -54,7 +54,7 @@ static int do_clone(void *arg) } #define __LXC_STACK_SIZE 4096 -pid_t lxc_clone(int (*fn)(void *), void *arg, int flags) +pid_t lxc_clone(int (*fn)(void *), void *arg, int flags, int *pidfd) { size_t stack_size; pid_t ret; @@ -66,9 +66,9 @@ pid_t lxc_clone(int (*fn)(void *), void *arg, int flags) stack_size = __LXC_STACK_SIZE; #ifdef __ia64__ - ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg); + ret = __clone2(do_clone, stack, stack_size, flags | SIGCHLD, &clone_arg, pidfd); #else - ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg); + ret = clone(do_clone, stack + stack_size, flags | SIGCHLD, &clone_arg, pidfd); #endif if (ret < 0) SYSERROR("Failed to clone (%#x)", flags); diff --git a/src/lxc/namespace.h b/src/lxc/namespace.h index ab583da76..f2c2ad82c 100644 --- a/src/lxc/namespace.h +++ b/src/lxc/namespace.h @@ -133,7 +133,7 @@ int clone(int (*fn)(void *), void *child_stack, * - should call lxc_raw_getpid(): * The child should use lxc_raw_getpid() to retrieve its pid. */ -extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags); +extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags, int *pidfd); extern int lxc_namespace_2_cloneflag(const char *namespace); extern int lxc_namespace_2_ns_idx(const char *namespace); diff --git a/src/lxc/start.c b/src/lxc/start.c index 34798292c..51969697e 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -406,7 +406,9 @@ static int signal_handler(int fd, uint32_t events, void *data, } 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); else kill(hdlr->pid, SIGTERM); @@ -416,7 +418,10 @@ static int signal_handler(int fd, uint32_t events, void *data, } 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, siginfo.ssi_signo, NULL, 0); else @@ -665,6 +670,8 @@ void lxc_zero_handler(struct lxc_handler *handler) handler->pinfd = -1; + handler->pidfd = -EBADF; + handler->proc_pidfd = -EBADF; handler->sigfd = -1; @@ -687,6 +694,9 @@ void lxc_free_handler(struct lxc_handler *handler) if (handler->pinfd >= 0) close(handler->pinfd); + if (handler->pidfd >= 0) + close(handler->pidfd); + if (handler->proc_pidfd >= 0) close(handler->proc_pidfd); @@ -734,6 +744,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, handler->conf = conf; handler->lxcpath = lxcpath; handler->pinfd = -1; + handler->pidfd = -EBADF; handler->proc_pidfd = -EBADF; handler->sigfd = -EBADF; handler->init_died = false; @@ -1096,19 +1107,23 @@ void lxc_fini(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); - 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); - if (ret < 0) - SYSERROR("Failed to send SIGKILL to %d", handler->pid); - } + else if (handler->pid > 0) + ret = kill(handler->pid, SIGKILL); + if (ret < 0) + 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) @@ -1601,7 +1616,8 @@ static inline int do_share_ns(void *arg) flags = handler->ns_on_clone_flags; 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) return -1; @@ -1735,7 +1751,7 @@ static int lxc_spawn(struct lxc_handler *handler) pid_t attacher_pid; attacher_pid = lxc_clone(do_share_ns, handler, - CLONE_VFORK | CLONE_VM | CLONE_FILES); + CLONE_VFORK | CLONE_VM | CLONE_FILES, NULL); if (attacher_pid < 0) { SYSERROR(LXC_CLONE_ERROR); goto out_delete_net; @@ -1748,7 +1764,8 @@ static int lxc_spawn(struct lxc_handler *handler) } } else { 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) { SYSERROR(LXC_CLONE_ERROR); @@ -1756,9 +1773,11 @@ static int lxc_spawn(struct lxc_handler *handler) } TRACE("Cloned child process %d", handler->pid); - handler->proc_pidfd = proc_pidfd_open(handler->pid); - if (handler->proc_pidfd < 0 && (errno != ENOSYS)) - goto out_delete_net; + if (handler->pidfd < 0) { + handler->proc_pidfd = proc_pidfd_open(handler->pid); + if (handler->proc_pidfd < 0 && (errno != ENOSYS)) + goto out_delete_net; + } for (i = 0; i < LXC_NS_MAX; i++) if (handler->ns_on_clone_flags & ns_info[i].clone_flag) diff --git a/src/lxc/start.h b/src/lxc/start.h index 305782f27..a3a5b4d54 100644 --- a/src/lxc/start.h +++ b/src/lxc/start.h @@ -102,6 +102,9 @@ struct lxc_handler { /* The child's pid. */ pid_t pid; + /* The child's pidfd. */ + int pidfd; + /* * File descriptor for the /proc/ directory of the container's * init process. diff --git a/src/lxc/storage/nbd.c b/src/lxc/storage/nbd.c index ab4f752c9..dc68ee623 100644 --- a/src/lxc/storage/nbd.c +++ b/src/lxc/storage/nbd.c @@ -266,7 +266,7 @@ static bool clone_attach_nbd(const char *nbd, const char *path) data.nbd = nbd; data.path = path; - pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID); + pid = lxc_clone(do_attach_nbd, &data, CLONE_NEWPID, NULL); if (pid < 0) return false; diff --git a/src/lxc/tools/lxc_unshare.c b/src/lxc/tools/lxc_unshare.c index 1bc04ce92..421d92c2a 100644 --- a/src/lxc/tools/lxc_unshare.c +++ b/src/lxc/tools/lxc_unshare.c @@ -388,7 +388,7 @@ int main(int argc, char *argv[]) start_arg.want_hostname = my_args.want_hostname; start_arg.want_default_mounts = my_args.want_default_mounts; - pid = lxc_clone(do_start, &start_arg, my_args.flags); + pid = lxc_clone(do_start, &start_arg, my_args.flags, NULL); if (pid < 0) { ERROR("Failed to clone"); free_ifname_list();