raw_syscalls: add initial support for pidfd_send_signal()

Well, I added this syscall so we better use it. :) Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 192023dd
...@@ -108,3 +108,14 @@ pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags) ...@@ -108,3 +108,14 @@ pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags)
return pid; return pid;
} }
int lxc_raw_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
unsigned int flags)
{
#ifdef __NR_pidfd_send_signal
syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
#else
errno = ENOSYS;
#endif
return -1;
}
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <sched.h> #include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
...@@ -92,4 +93,7 @@ static inline pid_t lxc_raw_gettid(void) ...@@ -92,4 +93,7 @@ static inline pid_t lxc_raw_gettid(void)
#endif #endif
} }
extern int lxc_raw_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
unsigned int flags);
#endif /* __LXC_RAW_SYSCALL_H */ #endif /* __LXC_RAW_SYSCALL_H */
...@@ -406,14 +406,21 @@ static int signal_handler(int fd, uint32_t events, void *data, ...@@ -406,14 +406,21 @@ static int signal_handler(int fd, uint32_t events, void *data,
} }
if (siginfo.ssi_signo == SIGHUP) { if (siginfo.ssi_signo == SIGHUP) {
kill(hdlr->pid, SIGTERM); if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd, SIGTERM, NULL, 0);
else
kill(hdlr->pid, SIGTERM);
INFO("Killing %d since terminal hung up", hdlr->pid); INFO("Killing %d since terminal hung up", hdlr->pid);
return hdlr->init_died ? LXC_MAINLOOP_CLOSE return hdlr->init_died ? LXC_MAINLOOP_CLOSE
: LXC_MAINLOOP_CONTINUE; : LXC_MAINLOOP_CONTINUE;
} }
if (siginfo.ssi_signo != SIGCHLD) { if (siginfo.ssi_signo != SIGCHLD) {
kill(hdlr->pid, siginfo.ssi_signo); if (hdlr->proc_pidfd >= 0)
lxc_raw_pidfd_send_signal(hdlr->proc_pidfd,
siginfo.ssi_signo, NULL, 0);
else
kill(hdlr->pid, siginfo.ssi_signo);
INFO("Forwarded signal %d to pid %d", siginfo.ssi_signo, hdlr->pid); INFO("Forwarded signal %d to pid %d", siginfo.ssi_signo, hdlr->pid);
return hdlr->init_died ? LXC_MAINLOOP_CLOSE return hdlr->init_died ? LXC_MAINLOOP_CLOSE
: LXC_MAINLOOP_CONTINUE; : LXC_MAINLOOP_CONTINUE;
...@@ -658,6 +665,8 @@ void lxc_zero_handler(struct lxc_handler *handler) ...@@ -658,6 +665,8 @@ void lxc_zero_handler(struct lxc_handler *handler)
handler->pinfd = -1; handler->pinfd = -1;
handler->proc_pidfd = -EBADF;
handler->sigfd = -1; handler->sigfd = -1;
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
...@@ -678,6 +687,9 @@ void lxc_free_handler(struct lxc_handler *handler) ...@@ -678,6 +687,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->proc_pidfd >= 0)
close(handler->proc_pidfd);
if (handler->sigfd >= 0) if (handler->sigfd >= 0)
close(handler->sigfd); close(handler->sigfd);
...@@ -722,6 +734,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf, ...@@ -722,6 +734,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->proc_pidfd = -EBADF;
handler->sigfd = -EBADF; handler->sigfd = -EBADF;
handler->init_died = false; handler->init_died = false;
handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1; handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
...@@ -1088,7 +1101,7 @@ void lxc_abort(const char *name, struct lxc_handler *handler) ...@@ -1088,7 +1101,7 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
lxc_set_state(name, handler, ABORTING); lxc_set_state(name, handler, ABORTING);
if (handler->pid > 0) { if (handler->pid > 0) {
ret = kill(handler->pid, SIGKILL); ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0);
if (ret < 0) if (ret < 0)
SYSERROR("Failed to send SIGKILL to %d", handler->pid); SYSERROR("Failed to send SIGKILL to %d", handler->pid);
} }
...@@ -1595,6 +1608,27 @@ static inline int do_share_ns(void *arg) ...@@ -1595,6 +1608,27 @@ static inline int do_share_ns(void *arg)
return 0; return 0;
} }
static int proc_pidfd_open(pid_t pid)
{
__do_close_prot_errno int proc_pidfd = -EBADF;
char path[100];
snprintf(path, sizeof(path), "/proc/%d", pid);
proc_pidfd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (proc_pidfd < 0) {
SYSERROR("Failed to open %s", path);
return -1;
}
/* Test whether we can send signals. */
if (lxc_raw_pidfd_send_signal(proc_pidfd, 0, NULL, 0)) {
SYSERROR("Failed to send signal through pidfd");
return -1;
}
return move_fd(proc_pidfd);
}
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which /* lxc_spawn() performs crucial setup tasks and clone()s the new process which
* exec()s the requested container binary. * exec()s the requested container binary.
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed * Note that lxc_spawn() runs in the parent namespaces. Any operations performed
...@@ -1722,6 +1756,10 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1722,6 +1756,10 @@ static int lxc_spawn(struct lxc_handler *handler)
} }
TRACE("Cloned child process %d", handler->pid); 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;
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)
INFO("Cloned %s", ns_info[i].flag_name); INFO("Cloned %s", ns_info[i].flag_name);
......
...@@ -102,6 +102,12 @@ struct lxc_handler { ...@@ -102,6 +102,12 @@ struct lxc_handler {
/* The child's pid. */ /* The child's pid. */
pid_t pid; pid_t pid;
/*
* File descriptor for the /proc/<pid> directory of the container's
* init process.
*/
int proc_pidfd;
/* The monitor's pid. */ /* The monitor's pid. */
pid_t monitor_pid; pid_t monitor_pid;
......
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