]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
confile: add lxc.seccomp.notify.proxy
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 25 Apr 2019 12:51:51 +0000 (14:51 +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/af_unix.c
src/lxc/af_unix.h
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/start.c

index 06700fac1ead675980f66c19facd61e8930d1fcc..328f891f0b7a3d7384acc044ab75961370e03b0b 100644 (file)
@@ -316,3 +316,73 @@ int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size)
 out:
        return ret;
 }
+
+int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path)
+{
+       size_t len;
+
+       len = strlen(path);
+       if (len == 0)
+               return minus_one_set_errno(EINVAL);
+       if (path[0] != '/' && path[0] != '@')
+               return minus_one_set_errno(EINVAL);
+       if (path[1] == '\0')
+               return minus_one_set_errno(EINVAL);
+
+       if (len + 1 > sizeof(ret->sun_path))
+               return minus_one_set_errno(EINVAL);
+
+       *ret = (struct sockaddr_un){
+           .sun_family = AF_UNIX,
+       };
+
+       if (path[0] == '@') {
+               memcpy(ret->sun_path + 1, path + 1, len);
+               return (int)(offsetof(struct sockaddr_un, sun_path) + len);
+       }
+
+       memcpy(ret->sun_path, path, len + 1);
+       return (int)(offsetof(struct sockaddr_un, sun_path) + len + 1);
+}
+
+int lxc_unix_connect(struct sockaddr_un *addr)
+{
+       __do_close_prot_errno int fd = -EBADF;
+       int ret;
+       ssize_t len;
+
+       fd = socket(PF_UNIX, SOCK_STREAM, SOCK_CLOEXEC);
+       if (fd < 0)
+               return -1;
+
+       if (addr->sun_path[0] == '\0')
+               len = strlen(&addr->sun_path[1]);
+       else
+               len = strlen(&addr->sun_path[0]);
+       ret = connect(fd, (struct sockaddr *)&addr,
+                     offsetof(struct sockaddr_un, sun_path) + len + 1);
+       if (ret < 0)
+               return -1;
+
+       return move_fd(fd);
+}
+
+int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout)
+{
+       struct timeval out = {0};
+       int ret;
+
+       out.tv_sec = snd_timeout;
+       ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&out,
+                        sizeof(out));
+       if (ret < 0)
+               return -1;
+
+       out.tv_sec = rcv_timeout;
+       ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&out,
+                        sizeof(out));
+       if (ret < 0)
+               return -1;
+
+       return 0;
+}
index f2c2fdcc6eeae2d8f1b77aaeae7b66e60e2a9252..3ae5954983d811ec28aea5ef019a2c5dcfebcbd9 100644 (file)
@@ -25,6 +25,8 @@
 #define __LXC_AF_UNIX_H
 
 #include <stdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 /* does not enforce \0-termination */
 extern int lxc_abstract_unix_open(const char *path, int type, int flags);
@@ -37,5 +39,8 @@ extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
                                      void *data, size_t size);
 extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size);
 extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size);
+extern int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path);
+extern int lxc_unix_connect(struct sockaddr_un *addr);
+extern int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout);
 
 #endif /* __LXC_AF_UNIX_H */
index 453763243a42347d738afe2c2e762aa5d87b9557..db00c70e993c3a822ac5f2ba6dd806db75123c62 100644 (file)
@@ -2756,6 +2756,7 @@ struct lxc_conf *lxc_conf_init(void)
        new->has_seccomp_notify = false;
        new->seccomp_notify_fd = -EBADF;
        new->seccomp_notify_proxy_fd = -EBADF;
+       memset(&new->seccomp_notify_proxy_addr, 0, sizeof(new->seccomp_notify_proxy_addr));
        new->seccomp_notify_req = NULL;
        new->seccomp_notify_resp = NULL;
 #endif
index f00f477c36cd5ba30880879d63ae1fe4ab2213c9..f7b8e9724827b66db830d306d1c0e7acb8da309e 100644 (file)
@@ -304,6 +304,7 @@ struct lxc_conf {
        bool has_seccomp_notify;
        int seccomp_notify_fd;
        int seccomp_notify_proxy_fd;
+       struct sockaddr_un seccomp_notify_proxy_addr;
        struct seccomp_notif *seccomp_notify_req;
        struct seccomp_notif_resp *seccomp_notify_resp;
 #endif
index 8f94635d1bfc0a025687f40645fa6afadee348c4..da5e45ce3cd44c2ebf4d3f8e0169eff42e2f63a7 100644 (file)
@@ -46,6 +46,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include "af_unix.h"
 #include "conf.h"
 #include "config.h"
 #include "confile.h"
@@ -147,6 +148,7 @@ lxc_config_define(rootfs_options);
 lxc_config_define(rootfs_path);
 lxc_config_define(seccomp_profile);
 lxc_config_define(seccomp_allow_nesting);
+lxc_config_define(seccomp_notify_proxy);
 lxc_config_define(selinux_context);
 lxc_config_define(signal_halt);
 lxc_config_define(signal_reboot);
@@ -234,6 +236,7 @@ static struct lxc_config_t config_jump_table[] = {
        { "lxc.rootfs.options",            set_config_rootfs_options,              get_config_rootfs_options,              clr_config_rootfs_options,            },
        { "lxc.rootfs.path",               set_config_rootfs_path,                 get_config_rootfs_path,                 clr_config_rootfs_path,               },
        { "lxc.seccomp.allow_nesting",     set_config_seccomp_allow_nesting,       get_config_seccomp_allow_nesting,       clr_config_seccomp_allow_nesting,     },
+       { "lxc.seccomp.notify.proxy",      set_config_seccomp_notify_proxy,        get_config_seccomp_notify_proxy,        clr_config_seccomp_notify_proxy,      },
        { "lxc.seccomp.profile",           set_config_seccomp_profile,             get_config_seccomp_profile,             clr_config_seccomp_profile,           },
        { "lxc.selinux.context",           set_config_selinux_context,             get_config_selinux_context,             clr_config_selinux_context,           },
        { "lxc.signal.halt",               set_config_signal_halt,                 get_config_signal_halt,                 clr_config_signal_halt,               },
@@ -784,9 +787,31 @@ static int set_config_seccomp_allow_nesting(const char *key, const char *value,
                return -1;
 
        if (lxc_conf->seccomp_allow_nesting > 1)
+               return minus_one_set_errno(EINVAL);
+
+       return 0;
+}
+
+static int set_config_seccomp_notify_proxy(const char *key, const char *value,
+                                          struct lxc_conf *lxc_conf, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       const char *offset;
+
+       if (lxc_config_value_empty(value))
+               return clr_config_seccomp_notify_proxy(key, lxc_conf, NULL);
+
+       if (strncmp(value, "unix:", 5) != 0)
+               return minus_one_set_errno(EINVAL);
+
+       offset = value + 5;
+       if (lxc_unix_sockaddr(&lxc_conf->seccomp_notify_proxy_addr, offset) < 0)
                return -1;
 
        return 0;
+#else
+       return minus_one_set_errno(ENOSYS);
+#endif
 }
 
 static int set_config_seccomp_profile(const char *key, const char *value,
@@ -3704,6 +3729,19 @@ static int get_config_seccomp_allow_nesting(const char *key, char *retv,
        return lxc_get_conf_int(c, retv, inlen, c->seccomp_allow_nesting);
 }
 
+static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inlen,
+                                          struct lxc_conf *c, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       return lxc_get_conf_str(retv, inlen,
+                               (c->seccomp_notify_proxy_addr.sun_path[0]) == '/'
+                                   ? &c->seccomp_notify_proxy_addr.sun_path[0]
+                                   : &c->seccomp_notify_proxy_addr.sun_path[1]);
+#else
+       return minus_one_set_errno(ENOSYS);
+#endif
+}
+
 static int get_config_seccomp_profile(const char *key, char *retv, int inlen,
                                      struct lxc_conf *c, void *data)
 {
@@ -4294,6 +4332,18 @@ static inline int clr_config_seccomp_allow_nesting(const char *key,
        return 0;
 }
 
+static inline int clr_config_seccomp_notify_proxy(const char *key,
+                                                  struct lxc_conf *c, void *data)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       memset(&c->seccomp_notify_proxy_addr, 0,
+              sizeof(c->seccomp_notify_proxy_addr));
+       return 0;
+#else
+       return minus_one_set_errno(ENOSYS);
+#endif
+}
+
 static inline int clr_config_seccomp_profile(const char *key,
                                             struct lxc_conf *c, void *data)
 {
index b1b4a3af780e81d1614d4803a332e278560d3b4b..6d5913af6fb0637b2d1a2e3ded63bba507218b41 100644 (file)
@@ -593,7 +593,18 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
        if (handler->conf->has_seccomp_notify &&
-           handler->conf->seccomp_notify_proxy_fd >= 0) {
+           handler->conf->seccomp_notify_proxy_addr.sun_path[1] != '\0') {
+                __do_close_prot_errno int notify_fd = -EBADF;
+
+               notify_fd = lxc_unix_connect(&handler->conf->seccomp_notify_proxy_addr);
+               if (notify_fd < 0)
+                       goto out_mainloop_console;
+
+               /* 30 second timeout */
+               ret = lxc_socket_set_timeout(notify_fd, 30, 30);
+               if (ret)
+                       goto out_mainloop_console;
+
                ret = lxc_mainloop_add_handler(&descr,
                                               handler->conf->seccomp_notify_fd,
                                               seccomp_notify_handler, handler);
@@ -602,6 +613,8 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
                              handler->conf->seccomp_notify_fd);
                        goto out_mainloop_console;
                }
+
+               handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
        }
 #endif