]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
raw_syscalls: add initial support for pidfd_send_signal() 2977/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 6 May 2019 08:49:31 +0000 (10:49 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 6 May 2019 08:49:31 +0000 (10:49 +0200)
Well, I added this syscall so we better use it. :)

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/raw_syscalls.c
src/lxc/raw_syscalls.h
src/lxc/start.c
src/lxc/start.h

index 2e15575870727697aeccd7aaff91b1402efa6407..a16f6edf76231563ad9d63dfa2c9f8829455e51c 100644 (file)
@@ -108,3 +108,14 @@ pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags)
 
        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;
+}
index 224cf92fcafaa55b52adace13b59923a762fde5f..6c27f26a0b013302e3ba884db0ecb63b3e7ade03 100644 (file)
@@ -26,6 +26,7 @@
 #include <sched.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <signal.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
@@ -92,4 +93,7 @@ static inline pid_t lxc_raw_gettid(void)
 #endif
 }
 
+extern int lxc_raw_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
+                                    unsigned int flags);
+
 #endif /* __LXC_RAW_SYSCALL_H */
index 5209af35864f28eab057b2cf63b16bf873b03738..651511dbe35d008106bf4dd83da9c2ae0d0b351e 100644 (file)
@@ -406,14 +406,21 @@ static int signal_handler(int fd, uint32_t events, void *data,
        }
 
        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);
                return hdlr->init_died ? LXC_MAINLOOP_CLOSE
                                       : LXC_MAINLOOP_CONTINUE;
        }
 
        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);
                return hdlr->init_died ? LXC_MAINLOOP_CLOSE
                                       : LXC_MAINLOOP_CONTINUE;
@@ -658,6 +665,8 @@ void lxc_zero_handler(struct lxc_handler *handler)
 
        handler->pinfd = -1;
 
+       handler->proc_pidfd = -EBADF;
+
        handler->sigfd = -1;
 
        for (i = 0; i < LXC_NS_MAX; i++)
@@ -678,6 +687,9 @@ void lxc_free_handler(struct lxc_handler *handler)
        if (handler->pinfd >= 0)
                close(handler->pinfd);
 
+       if (handler->proc_pidfd >= 0)
+               close(handler->proc_pidfd);
+
        if (handler->sigfd >= 0)
                close(handler->sigfd);
 
@@ -722,6 +734,7 @@ struct lxc_handler *lxc_init_handler(const char *name, struct lxc_conf *conf,
        handler->conf = conf;
        handler->lxcpath = lxcpath;
        handler->pinfd = -1;
+       handler->proc_pidfd = -EBADF;
        handler->sigfd = -EBADF;
        handler->init_died = false;
        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)
        lxc_set_state(name, handler, ABORTING);
 
        if (handler->pid > 0) {
-               ret = kill(handler->pid, SIGKILL);
+               ret = lxc_raw_pidfd_send_signal(handler->proc_pidfd, SIGKILL, NULL, 0);
                if (ret < 0)
                        SYSERROR("Failed to send SIGKILL to %d", handler->pid);
        }
@@ -1595,6 +1608,27 @@ static inline int do_share_ns(void *arg)
        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
  * exec()s the requested container binary.
  * Note that lxc_spawn() runs in the parent namespaces. Any operations performed
@@ -1722,6 +1756,10 @@ 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;
+
        for (i = 0; i < LXC_NS_MAX; i++)
                if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
                        INFO("Cloned %s", ns_info[i].flag_name);
index 60607ccc125f02d22d45ccc2b867502cfb4b73de..305782f272bab848e183e1280adcb6e417cddd6e 100644 (file)
@@ -102,6 +102,12 @@ struct lxc_handler {
        /* The child's pid. */
        pid_t pid;
 
+       /*
+        * File descriptor for the /proc/<pid> directory of the container's
+        * init process.
+        */
+       int proc_pidfd;
+
        /* The monitor's pid. */
        pid_t monitor_pid;