]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
seccomp: send default answer and try to reconnect
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 25 Apr 2019 13:53:14 +0000 (15:53 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 25 Apr 2019 19:35:28 +0000 (21:35 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/seccomp.c

index 10b634f2b3a6c083778538765663a4f40a6de289..287da564d2aa78e19f3c199e346547a405d9a850 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/mount.h>
 #include <sys/utsname.h>
 
+#include "af_unix.h"
 #include "config.h"
 #include "log.h"
 #include "lxccontainer.h"
@@ -1290,12 +1291,51 @@ void lxc_seccomp_free(struct lxc_conf *conf)
 #endif
 }
 
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+static int seccomp_notify_reconnect(struct lxc_handler *handler)
+{
+       __do_close_prot_errno int notify_fd = -EBADF;
+
+       close_prot_errno_disarm(handler->conf->seccomp_notify_proxy_fd);
+
+       notify_fd = lxc_unix_connect(&handler->conf->seccomp_notify_proxy_addr);
+       if (notify_fd < 0) {
+               SYSERROR("Failed to reconnect to seccomp proxy");
+               return -1;
+       }
+
+       /* 30 second timeout */
+       if (lxc_socket_set_timeout(notify_fd, 30, 30)) {
+               SYSERROR("Failed to set socket timeout");
+               return -1;
+       }
+       handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
+       return 0;
+}
+#endif
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+static int seccomp_notify_default_answer(int fd, struct seccomp_notif *req,
+                                        struct seccomp_notif_resp *resp,
+                                        struct lxc_handler *handler)
+{
+       resp->id = req->id;
+       resp->error = -ENOSYS;
+
+       if (seccomp_notif_send_resp(fd, resp))
+               SYSERROR("Failed to send default message to seccomp");
+
+       return seccomp_notify_reconnect(handler);
+}
+#endif
+
 int seccomp_notify_handler(int fd, uint32_t events, void *data,
                           struct lxc_epoll_descr *descr)
 {
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       int ret;
+       int reconnect_count, ret;
+       ssize_t bytes;
        struct lxc_handler *hdlr = data;
        struct lxc_conf *conf = hdlr->conf;
        struct seccomp_notif *req = conf->seccomp_notify_req;
@@ -1303,31 +1343,48 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
        int listener_proxy_fd = conf->seccomp_notify_proxy_fd;
        struct seccomp_notify_proxy_msg msg;
 
-       if (listener_proxy_fd < 0)
+       if (listener_proxy_fd < 0) {
+               ERROR("No seccomp proxy registered");
                return minus_one_set_errno(EINVAL);
+       }
 
        ret = seccomp_notif_receive(fd, req);
-       if (ret)
-               return minus_one_set_errno(-ret);
+       if (ret) {
+               SYSERROR("Failed to read seccomp notification");
+               goto out;
+       }
 
        memcpy(&msg.req, req, sizeof(msg.req));
        msg.monitor_pid = hdlr->monitor_pid;
        msg.init_pid = hdlr->pid;
 
-       ret = lxc_send_nointr(listener_proxy_fd, &msg, sizeof(msg), MSG_NOSIGNAL);
-       if (ret < 0 || ret != (ssize_t)sizeof(msg))
-               return -1;
-
-       ret = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);
-       if (ret != (ssize_t)sizeof(msg))
-               return -1;
+       reconnect_count = 0;
+       do {
+               bytes = lxc_send_nointr(listener_proxy_fd, &msg, sizeof(msg),
+                                       MSG_NOSIGNAL);
+               if (bytes != (ssize_t)sizeof(msg)) {
+                       SYSERROR("Failed to forward message to seccomp proxy");
+                       if (seccomp_notify_default_answer(fd, req, resp, hdlr))
+                               goto out;
+               }
+       } while (reconnect_count++);
+
+       reconnect_count = 0;
+       do {
+               bytes = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);
+               if (bytes != (ssize_t)sizeof(msg)) {
+                       SYSERROR("Failed to receive message from seccomp proxy");
+                       if (seccomp_notify_default_answer(fd, req, resp, hdlr))
+                               goto out;
+               }
+       } while (reconnect_count++);
 
        memcpy(resp, &msg.resp, sizeof(*resp));
-
        ret = seccomp_notif_send_resp(fd, resp);
        if (ret)
-               return minus_one_set_errno(-ret);
+               SYSERROR("Failed to send seccomp notification");
 
+out:
        return 0;
 #else
        return -ENOSYS;