]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
seccomp: cleanup 2956/head
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 29 Apr 2019 08:16:01 +0000 (10:16 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 29 Apr 2019 13:17:31 +0000 (15:17 +0200)
Simplify and cleanup some of the seccomp code. This mainly focuses on removing
the open coding of various seccomp settings all over the code place in favor of
centralized helpers.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
14 files changed:
src/lxc/af_unix.c
src/lxc/attach.c
src/lxc/commands.c
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h
src/lxc/lxcseccomp.h
src/lxc/memory_utils.h
src/lxc/seccomp.c
src/lxc/start.c
src/tests/Makefile.am
src/tests/parse_config_file.c

index 328f891f0b7a3d7384acc044ab75961370e03b0b..275430a52a2a0e5347a895784dc31517927bdb07 100644 (file)
@@ -156,7 +156,8 @@ int lxc_abstract_unix_connect(const char *path)
 int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
                               void *data, size_t size)
 {
-       __do_free char *cmsgbuf;
+       __do_free char *cmsgbuf = NULL;
+       int ret;
        struct msghdr msg;
        struct iovec iov;
        struct cmsghdr *cmsg = NULL;
@@ -189,13 +190,19 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
 
-       return sendmsg(fd, &msg, MSG_NOSIGNAL);
+again:
+       ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
+       if (ret < 0)
+               if (errno == EINTR)
+                       goto again;
+
+       return ret;
 }
 
 int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
                               void *data, size_t size)
 {
-       __do_free char *cmsgbuf;
+       __do_free char *cmsgbuf = NULL;
        int ret;
        struct msghdr msg;
        struct iovec iov;
@@ -221,8 +228,15 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
 
+again:
        ret = recvmsg(fd, &msg, 0);
-       if (ret <= 0)
+       if (ret < 0) {
+               if (errno == EINTR)
+                       goto again;
+
+               goto out;
+       }
+       if (ret == 0)
                goto out;
 
        /*
index ac0450187bfe71d9382381a244b0891628813647..331434b26836bef1ad125bc51cd266f282c1f850 100644 (file)
@@ -608,8 +608,8 @@ static bool fetch_seccomp(struct lxc_container *c, lxc_attach_options_t *options
 
        if (!(options->namespaces & CLONE_NEWNS) ||
            !(options->attach_flags & LXC_ATTACH_LSM)) {
-               free(c->lxc_conf->seccomp);
-               c->lxc_conf->seccomp = NULL;
+               free(c->lxc_conf->seccomp.seccomp);
+               c->lxc_conf->seccomp.seccomp = NULL;
                return true;
        }
 
@@ -852,7 +852,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
        }
 
        if (init_ctx->container && init_ctx->container->lxc_conf &&
-           init_ctx->container->lxc_conf->seccomp) {
+           init_ctx->container->lxc_conf->seccomp.seccomp) {
                struct lxc_conf *conf = init_ctx->container->lxc_conf;
 
                ret = lxc_seccomp_load(conf);
@@ -861,18 +861,9 @@ static int attach_child_main(struct attach_clone_payload *payload)
 
                TRACE("Loaded seccomp profile");
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-               if (conf->has_seccomp_notify) {
-                       ret = lxc_abstract_unix_send_fds(payload->ipc_socket,
-                                                        &conf->seccomp_notify_fd,
-                                                        1, NULL, 0);
-                       close_prot_errno_disarm(conf->seccomp_notify_fd);
-                       if (ret < 0)
-                               goto on_error;
-
-                       TRACE("Sent seccomp listener fd to parent");
-               }
-#endif
+               ret = lxc_seccomp_send_notifier_fd(&conf->seccomp, payload->ipc_socket);
+               if (ret < 0)
+                       goto on_error;
        }
 
        close(payload->ipc_socket);
@@ -1326,24 +1317,13 @@ int lxc_attach(const char *name, const char *lxcpath,
                        TRACE("Sent LSM label file descriptor %d to child", labelfd);
                }
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-               if (conf->seccomp && conf->has_seccomp_notify) {
-                       ret = lxc_abstract_unix_recv_fds(ipc_sockets[0],
-                                                        &conf->seccomp_notify_fd,
-                                                        1, NULL, 0);
-                       if (ret < 0)
-                               goto close_mainloop;
+               ret = lxc_seccomp_recv_notifier_fd(&conf->seccomp, ipc_sockets[0]);
+               if (ret < 0)
+                       goto close_mainloop;
 
-                       TRACE("Retrieved seccomp listener fd %d from child",
-                             conf->seccomp_notify_fd);
-                       ret = lxc_cmd_seccomp_notify_add_listener(name, lxcpath,
-                                                                 conf->seccomp_notify_fd,
-                                                                 -1, 0);
-                       close_prot_errno_disarm(conf->seccomp_notify_fd);
-                       if (ret < 0)
-                               goto close_mainloop;
-               }
-#endif
+               ret = lxc_seccomp_add_notifier(name, lxcpath, &conf->seccomp);
+               if (ret < 0)
+                       goto close_mainloop;
 
                /* We're done, the child process should now execute whatever it
                 * is that the user requested. The parent can now track it with
index e429904652307827ea3c2717438b67d46ae79c43..90e3c5863d41f13b217c76fef4fd8d9aab65f96b 100644 (file)
@@ -1053,7 +1053,7 @@ int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
                                        /* unused */ unsigned int flags)
 {
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#ifdef HAVE_SECCOMP_NOTIFY
        int ret, stopped;
        struct lxc_cmd_rr cmd = {
                .req = {
@@ -1080,43 +1080,39 @@ static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
                                                        struct lxc_epoll_descr *descr)
 {
        struct lxc_cmd_rsp rsp = {0};
-       int ret;
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#ifdef HAVE_SECCOMP_NOTIFY
+       int ret;
        __do_close_prot_errno int recv_fd = -EBADF;
        int notify_fd = -EBADF;
 
-       if (!handler->conf->has_seccomp_notify ||
-           handler->conf->seccomp_notify_proxy_fd < 0) {
-               rsp.ret = -EINVAL;
-               goto send_error;
+       ret = lxc_abstract_unix_recv_fds(fd, &recv_fd, 1, NULL, 0);
+       if (ret <= 0) {
+               rsp.ret = -errno;
+               goto out;
        }
 
-       ret = lxc_abstract_unix_recv_fds(fd, &recv_fd, 1, NULL, 0);
-       if (ret <= 0)
-               goto reap_client_fd;
+       if (!handler->conf->seccomp.notifier.wants_supervision ||
+           handler->conf->seccomp.notifier.proxy_fd < 0) {
+               SYSERROR("No seccomp proxy fd specified");
+               rsp.ret = -EINVAL;
+               goto out;
+       }
 
-       ret = lxc_mainloop_add_handler(descr, notify_fd, seccomp_notify_handler,
+       ret = lxc_mainloop_add_handler(descr, recv_fd, seccomp_notify_handler,
                                       handler);
+       if (ret < 0) {
+               rsp.ret = -errno;
+               goto out;
+       }
        notify_fd = move_fd(recv_fd);
-       if (ret < 0)
-               goto reap_client_fd;
 
-send_error:
+out:
 #else
        rsp.ret = -ENOSYS;
-#endif
-       ret = lxc_cmd_rsp_send(fd, &rsp);
-       if (ret < 0)
-               goto reap_client_fd;
-
-       return 0;
 
-reap_client_fd:
-       /* Special indicator to lxc_cmd_handler() to close the fd and do
-        * related cleanup.
-        */
-       return 1;
+#endif
+       return lxc_cmd_rsp_send(fd, &rsp);
 }
 
 static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
index db00c70e993c3a822ac5f2ba6dd806db75123c62..ec9543f743de8ba1ced5f1ca2ed57520cff84346 100644 (file)
@@ -2752,14 +2752,6 @@ struct lxc_conf *lxc_conf_init(void)
        new->lsm_aa_profile = NULL;
        lxc_list_init(&new->lsm_aa_raw);
        new->lsm_se_context = NULL;
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       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
        new->tmp_umount_proc = false;
        new->tmp_umount_proc = 0;
        new->shmount.path_host = NULL;
@@ -2771,6 +2763,7 @@ struct lxc_conf *lxc_conf_init(void)
        new->init_gid = 0;
        memset(&new->cgroup_meta, 0, sizeof(struct lxc_cgroup));
        memset(&new->ns_share, 0, sizeof(char *) * LXC_NS_MAX);
+       seccomp_conf_init(new);
 
        return new;
 }
@@ -4074,7 +4067,7 @@ void lxc_conf_free(struct lxc_conf *conf)
        free(conf->lsm_aa_profile);
        free(conf->lsm_aa_profile_computed);
        free(conf->lsm_se_context);
-       lxc_seccomp_free(conf);
+       lxc_seccomp_free(&conf->seccomp);
        lxc_clear_config_caps(conf);
        lxc_clear_config_keepcaps(conf);
        lxc_clear_cgroups(conf, "lxc.cgroup", CGROUP_SUPER_MAGIC);
index f7b8e9724827b66db830d306d1c0e7acb8da309e..2664a1527ce4f600e37a591bfe1b5ff4d117535d 100644 (file)
@@ -38,6 +38,7 @@
 #include "compiler.h"
 #include "config.h"
 #include "list.h"
+#include "lxcseccomp.h"
 #include "ringbuf.h"
 #include "start.h"
 #include "terminal.h"
@@ -295,19 +296,7 @@ struct lxc_conf {
        struct lxc_list lsm_aa_raw;
        char *lsm_se_context;
        bool tmp_umount_proc;
-       char *seccomp;  /* filename with the seccomp rules */
-       unsigned int seccomp_allow_nesting;
-#if HAVE_SCMP_FILTER_CTX
-       scmp_filter_ctx seccomp_ctx;
-#endif
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       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
+       struct lxc_seccomp seccomp;
        int maincmd_fd;
        unsigned int autodev;  /* if 1, mount and fill a /dev at start */
        int haltsignal; /* signal used to halt container */
index da5e45ce3cd44c2ebf4d3f8e0169eff42e2f63a7..efbac0c3d465a11502ea05b67513e8d9ec759546 100644 (file)
@@ -780,22 +780,27 @@ static int add_hook(struct lxc_conf *lxc_conf, int which, char *hook)
 static int set_config_seccomp_allow_nesting(const char *key, const char *value,
                                            struct lxc_conf *lxc_conf, void *data)
 {
+#ifdef HAVE_SECCOMP
        if (lxc_config_value_empty(value))
                return clr_config_seccomp_allow_nesting(key, lxc_conf, NULL);
 
-       if (lxc_safe_uint(value, &lxc_conf->seccomp_allow_nesting) < 0)
+       if (lxc_safe_uint(value, &lxc_conf->seccomp.allow_nesting) < 0)
                return -1;
 
-       if (lxc_conf->seccomp_allow_nesting > 1)
+       if (lxc_conf->seccomp.allow_nesting > 1)
                return minus_one_set_errno(EINVAL);
 
        return 0;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
 }
 
 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
+#ifdef HAVE_SECCOMP_NOTIFY
        const char *offset;
 
        if (lxc_config_value_empty(value))
@@ -805,7 +810,7 @@ static int set_config_seccomp_notify_proxy(const char *key, const char *value,
                return minus_one_set_errno(EINVAL);
 
        offset = value + 5;
-       if (lxc_unix_sockaddr(&lxc_conf->seccomp_notify_proxy_addr, offset) < 0)
+       if (lxc_unix_sockaddr(&lxc_conf->seccomp.notifier.proxy_addr, offset) < 0)
                return -1;
 
        return 0;
@@ -817,7 +822,7 @@ static int set_config_seccomp_notify_proxy(const char *key, const char *value,
 static int set_config_seccomp_profile(const char *key, const char *value,
                                      struct lxc_conf *lxc_conf, void *data)
 {
-       return set_config_path_item(&lxc_conf->seccomp, value);
+       return set_config_path_item(&lxc_conf->seccomp.seccomp, value);
 }
 
 static int set_config_execute_cmd(const char *key, const char *value,
@@ -3726,17 +3731,22 @@ static int get_config_seccomp_allow_nesting(const char *key, char *retv,
                                            int inlen, struct lxc_conf *c,
                                            void *data)
 {
-       return lxc_get_conf_int(c, retv, inlen, c->seccomp_allow_nesting);
+#ifdef HAVE_SECCOMP
+       return lxc_get_conf_int(c, retv, inlen, c->seccomp.allow_nesting);
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
 }
 
 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
+#ifdef HAVE_SECCOMP_NOTIFY
        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]);
+                               (c->seccomp.notifier.proxy_addr.sun_path[0]) == '/'
+                                   ? &c->seccomp.notifier.proxy_addr.sun_path[0]
+                                   : &c->seccomp.notifier.proxy_addr.sun_path[1]);
 #else
        return minus_one_set_errno(ENOSYS);
 #endif
@@ -3745,7 +3755,7 @@ static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inle
 static int get_config_seccomp_profile(const char *key, char *retv, int inlen,
                                      struct lxc_conf *c, void *data)
 {
-       return lxc_get_conf_str(retv, inlen, c->seccomp);
+       return lxc_get_conf_str(retv, inlen, c->seccomp.seccomp);
 }
 
 static int get_config_autodev(const char *key, char *retv, int inlen,
@@ -4328,16 +4338,21 @@ static inline int clr_config_console_size(const char *key, struct lxc_conf *c,
 static inline int clr_config_seccomp_allow_nesting(const char *key,
                                                   struct lxc_conf *c, void *data)
 {
-       c->seccomp_allow_nesting = 0;
+#ifdef HAVE_SECCOMP
+       c->seccomp.allow_nesting = 0;
        return 0;
+#else
+       errno = ENOSYS;
+       return -1;
+#endif
 }
 
 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));
+#ifdef HAVE_SECCOMP_NOTIFY
+       memset(&c->seccomp.notifier.proxy_addr, 0,
+              sizeof(c->seccomp.notifier.proxy_addr));
        return 0;
 #else
        return minus_one_set_errno(ENOSYS);
@@ -4347,8 +4362,8 @@ static inline int clr_config_seccomp_notify_proxy(const char *key,
 static inline int clr_config_seccomp_profile(const char *key,
                                             struct lxc_conf *c, void *data)
 {
-       free(c->seccomp);
-       c->seccomp = NULL;
+       free(c->seccomp.seccomp);
+       c->seccomp.seccomp = NULL;
        return 0;
 }
 
index e16639d4855328fd353a9817ae688798576a098a..98f86a24e4075b0d08ac4a2890c42ab753943eaa 100644 (file)
@@ -5229,7 +5229,6 @@ out:
 
 static int do_lxcapi_seccomp_notify(struct lxc_container *c, unsigned int cmd, int fd)
 {
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
        if (!c || !c->lxc_conf)
                return minus_one_set_errno(-EINVAL);
 
@@ -5238,13 +5237,10 @@ static int do_lxcapi_seccomp_notify(struct lxc_container *c, unsigned int cmd, i
                if (fd)
                        return minus_one_set_errno(EINVAL);
 
-               return c->lxc_conf->seccomp_notify_fd;
+               return lxc_seccomp_get_notify_fd(&c->lxc_conf->seccomp);
        }
 
        return minus_one_set_errno(EINVAL);
-#else
-       return minus_one_set_errno(ENOSYS);
-#endif
 }
 
 WRAP_API_2(int, lxcapi_seccomp_notify, unsigned int, int)
index 2bd3271149e201e3f5a2792e8b9cb9d51ca5377b..e2e788993d580d7b41867a7915fb5e949794094e 100644 (file)
@@ -31,7 +31,8 @@
 
 #include <lxc/attach_options.h>
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#ifdef SCMP_ACT_USER_NOTIF
+#include <linux/seccomp.h>
 #include <seccomp.h>
 #endif
 
@@ -69,7 +70,7 @@ enum {
        LXC_SECCOMP_NOTIFY_MAX,
 };
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#ifdef SCMP_ACT_USER_NOTIF
 struct seccomp_notify_proxy_msg {
        uint32_t version;
        struct seccomp_notif req;
index 530fffd80a1c416d09deca360e20195a4033b87b..aafe09f127320d5670f16e4fcfcbc21538a69347 100644 (file)
 #ifndef __LXC_LXCSECCOMP_H
 #define __LXC_LXCSECCOMP_H
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
 #include <errno.h>
 #ifdef HAVE_SECCOMP
+#include <linux/seccomp.h>
 #include <seccomp.h>
 #endif
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
 
 #include "conf.h"
+#include "config.h"
+#include "memory_utils.h"
+
+struct lxc_conf;
+struct lxc_epoll_descr;
+struct lxc_handler;
 
 #ifdef HAVE_SECCOMP
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+struct seccomp_notify {
+       bool wants_supervision;
+       int notify_fd;
+       int proxy_fd;
+       struct sockaddr_un proxy_addr;
+       struct seccomp_notif *req_buf;
+       struct seccomp_notif_resp *rsp_buf;
+};
+
+#define HAVE_SECCOMP_NOTIFY 1
+
+#endif /* HAVE_DECL_SECCOMP_NOTIF_GET_FD */
+
+struct lxc_seccomp {
+       char *seccomp;
+#if HAVE_SCMP_FILTER_CTX
+       unsigned int allow_nesting;
+       scmp_filter_ctx seccomp_ctx;
+#endif /* HAVE_SCMP_FILTER_CTX */
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       struct seccomp_notify notifier;
+#endif /* HAVE_DECL_SECCOMP_NOTIF_GET_FD */
+};
+
 extern int lxc_seccomp_load(struct lxc_conf *conf);
 extern int lxc_read_seccomp_config(struct lxc_conf *conf);
-extern void lxc_seccomp_free(struct lxc_conf *conf);
+extern void lxc_seccomp_free(struct lxc_seccomp *seccomp);
 extern int seccomp_notify_handler(int fd, uint32_t events, void *data,
                                  struct lxc_epoll_descr *descr);
-
+extern void seccomp_conf_init(struct lxc_conf *conf);
+extern int lxc_seccomp_setup_notifier(struct lxc_seccomp *seccomp,
+                                     struct lxc_epoll_descr *descr,
+                                     struct lxc_handler *handler);
+extern int lxc_seccomp_send_notifier_fd(struct lxc_seccomp *seccomp,
+                                       int socket_fd);
+extern int lxc_seccomp_recv_notifier_fd(struct lxc_seccomp *seccomp,
+                                       int socket_fd);
+extern int lxc_seccomp_add_notifier(const char *name, const char *lxcpath,
+                                   struct lxc_seccomp *seccomp);
+static inline int lxc_seccomp_get_notify_fd(struct lxc_seccomp *seccomp)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       return seccomp->notifier.notify_fd;
 #else
+       errno = ENOSYS;
+       return -EBADF;
+#endif
+}
+
+#else /* HAVE_SECCOMP */
+
+struct lxc_seccomp {
+       char *seccomp;
+};
+
 static inline int lxc_seccomp_load(struct lxc_conf *conf)
 {
        return 0;
@@ -49,16 +114,50 @@ static inline int lxc_read_seccomp_config(struct lxc_conf *conf)
        return 0;
 }
 
-static inline void lxc_seccomp_free(struct lxc_conf *conf)
+static inline void lxc_seccomp_free(struct lxc_seccomp *seccomp)
 {
-       free(conf->seccomp);
-       conf->seccomp = NULL;
+       free_disarm(seccomp->seccomp);
 }
+
 static inline int seccomp_notify_handler(int fd, uint32_t events, void *data,
                                  struct lxc_epoll_descr *descr)
 {
        return -ENOSYS;
 }
-#endif
 
-#endif
+static inline void seccomp_conf_init(struct lxc_conf *conf)
+{
+}
+
+static inline int lxc_seccomp_setup_notifier(struct lxc_seccomp *seccomp,
+                                            struct lxc_epoll_descr *descr,
+                                            struct lxc_handler *handler)
+{
+       return 0;
+}
+
+static inline int lxc_seccomp_send_notifier_fd(struct lxc_seccomp *seccomp,
+                                              int socket_fd)
+{
+       return 0;
+}
+
+static inline int lxc_seccomp_recv_notifier_fd(struct lxc_seccomp *seccomp,
+                                       int socket_fd)
+{
+       return 0;
+}
+
+static inline int lxc_seccomp_add_notifier(const char *name, const char *lxcpath,
+                                          struct lxc_seccomp *seccomp)
+{
+       return 0;
+}
+
+static inline int lxc_seccomp_get_notify_fd(struct lxc_seccomp *seccomp)
+{
+       return -EBADF;
+}
+
+#endif /* HAVE_SECCOMP */
+#endif /* __LXC_LXCSECCOMP_H */
index c1dafb441a45380dffe1851b3264034dbf9166d6..b5220c18994f99f6719466f44945fa6980bc652b 100644 (file)
@@ -55,6 +55,12 @@ static inline void __auto_closedir__(DIR **d)
                fd = -EBADF;        \
        }
 
+#define free_disarm(ptr)       \
+       ({                     \
+               free(ptr);     \
+               move_ptr(ptr); \
+       })
+
 static inline void __auto_close__(int *fd)
 {
        close_prot_errno_disarm(*fd);
index 287da564d2aa78e19f3c199e346547a405d9a850..a63b6d69fb9b0d979b9c12c78519a22365dbce82 100644 (file)
 #include <sys/utsname.h>
 
 #include "af_unix.h"
+#include "commands.h"
 #include "config.h"
 #include "log.h"
 #include "lxccontainer.h"
 #include "lxcseccomp.h"
+#include "mainloop.h"
 #include "memory_utils.h"
 #include "utils.h"
 
@@ -63,7 +65,7 @@ static int parse_config_v1(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
                }
 
 #if HAVE_SCMP_FILTER_CTX
-               ret = seccomp_rule_add(conf->seccomp_ctx, SCMP_ACT_ALLOW, nr, 0);
+               ret = seccomp_rule_add(conf->seccomp.seccomp_ctx, SCMP_ACT_ALLOW, nr, 0);
 #else
                ret = seccomp_rule_add(SCMP_ACT_ALLOW, nr, 0);
 #endif
@@ -736,13 +738,13 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
        }
 
        if (default_policy_action != SCMP_ACT_KILL) {
-               ret = seccomp_reset(conf->seccomp_ctx, default_policy_action);
+               ret = seccomp_reset(conf->seccomp.seccomp_ctx, default_policy_action);
                if (ret != 0) {
                        ERROR("Error re-initializing Seccomp");
                        return -1;
                }
 
-               ret = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
+               ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
                if (ret < 0) {
                        errno = -ret;
                        SYSERROR("Failed to turn off no-new-privs");
@@ -750,7 +752,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
                }
 
 #ifdef SCMP_FLTATR_ATL_TSKIP
-               ret = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1);
+               ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1);
                if (ret < 0) {
                        errno = -ret;
                        SYSWARN("Failed to turn on seccomp nop-skip, continuing");
@@ -941,19 +943,19 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
                if ((rule.action == SCMP_ACT_USER_NOTIF) &&
-                   !conf->has_seccomp_notify) {
-                       ret = seccomp_attr_set(conf->seccomp_ctx,
+                   !conf->seccomp.notifier.wants_supervision) {
+                       ret = seccomp_attr_set(conf->seccomp.seccomp_ctx,
                                               SCMP_FLTATR_NEW_LISTENER, 1);
                        if (ret)
                                goto bad_rule;
 
-                       conf->has_seccomp_notify = true;
+                       conf->seccomp.notifier.wants_supervision = true;
                        TRACE("Set SCMP_FLTATR_NEW_LISTENER attribute");
                }
 #endif
 
                if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line,
-                                        conf->seccomp_ctx, &rule))
+                                        conf->seccomp.seccomp_ctx, &rule))
                        goto bad_rule;
 
                INFO("Added native rule for arch %d for %s action %d(%s)",
@@ -994,7 +996,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
        INFO("Merging compat seccomp contexts into main context");
        if (ctx.contexts[0]) {
                if (ctx.needs_merge[0]) {
-                       ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[0]);
+                       ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[0]);
                        if (ret < 0) {
                                ERROR("Failed to merge first compat seccomp "
                                      "context into main context");
@@ -1010,7 +1012,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
 
        if (ctx.contexts[1]) {
                if (ctx.needs_merge[1]) {
-                       ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[1]);
+                       ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[1]);
                        if (ret < 0) {
                                ERROR("Failed to merge first compat seccomp "
                                      "context into main context");
@@ -1026,7 +1028,7 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
 
        if (ctx.contexts[2]) {
                if (ctx.needs_merge[2]) {
-                       ret = seccomp_merge(conf->seccomp_ctx, ctx.contexts[2]);
+                       ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[2]);
                        if (ret < 0) {
                                ERROR("Failed to merge third compat seccomp "
                                      "context into main context");
@@ -1128,7 +1130,7 @@ static bool use_seccomp(const struct lxc_conf *conf)
        char *line = NULL;
        bool already_enabled = false, found = false;
 
-       if (conf->seccomp_allow_nesting > 0)
+       if (conf->seccomp.allow_nesting > 0)
                return true;
 
        f = fopen("/proc/self/status", "r");
@@ -1167,7 +1169,7 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
        int ret;
        FILE *f;
 
-       if (!conf->seccomp)
+       if (!conf->seccomp.seccomp)
                return 0;
 
        if (!use_seccomp(conf))
@@ -1175,8 +1177,8 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
 
 #if HAVE_SCMP_FILTER_CTX
        /* XXX for debug, pass in SCMP_ACT_TRAP */
-       conf->seccomp_ctx = seccomp_init(SCMP_ACT_KILL);
-       ret = !conf->seccomp_ctx;
+       conf->seccomp.seccomp_ctx = seccomp_init(SCMP_ACT_KILL);
+       ret = !conf->seccomp.seccomp_ctx;
 #else
        ret = seccomp_init(SCMP_ACT_KILL) < 0;
 #endif
@@ -1188,7 +1190,7 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
 /* turn off no-new-privs. We don't want it in lxc, and it breaks
  * with apparmor */
 #if HAVE_SCMP_FILTER_CTX
-       ret = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
+       ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0);
 #else
        ret = seccomp_attr_set(SCMP_FLTATR_CTL_NNP, 0);
 #endif
@@ -1199,16 +1201,16 @@ int lxc_read_seccomp_config(struct lxc_conf *conf)
        }
 
 #ifdef SCMP_FLTATR_ATL_TSKIP
-       ret = seccomp_attr_set(conf->seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1);
+       ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1);
        if (ret < 0) {
                errno = -ret;
                SYSWARN("Failed to turn on seccomp nop-skip, continuing");
        }
 #endif
 
-       f = fopen(conf->seccomp, "r");
+       f = fopen(conf->seccomp.seccomp, "r");
        if (!f) {
-               SYSERROR("Failed to open seccomp policy file %s", conf->seccomp);
+               SYSERROR("Failed to open seccomp policy file %s", conf->seccomp.seccomp);
                return -1;
        }
 
@@ -1222,14 +1224,14 @@ int lxc_seccomp_load(struct lxc_conf *conf)
 {
        int ret;
 
-       if (!conf->seccomp)
+       if (!conf->seccomp.seccomp)
                return 0;
 
        if (!use_seccomp(conf))
                return 0;
 
 #if HAVE_SCMP_FILTER_CTX
-       ret = seccomp_load(conf->seccomp_ctx);
+       ret = seccomp_load(conf->seccomp.seccomp_ctx);
 #else
        ret = seccomp_load();
 #endif
@@ -1245,7 +1247,7 @@ int lxc_seccomp_load(struct lxc_conf *conf)
        if ((lxc_log_get_level() <= LXC_LOG_LEVEL_TRACE ||
             conf->loglevel <= LXC_LOG_LEVEL_TRACE) &&
            lxc_log_fd >= 0) {
-               ret = seccomp_export_pfc(conf->seccomp_ctx, lxc_log_fd);
+               ret = seccomp_export_pfc(conf->seccomp.seccomp_ctx, lxc_log_fd);
                /* Just give an warning when export error */
                if (ret < 0) {
                        errno = -ret;
@@ -1255,14 +1257,14 @@ int lxc_seccomp_load(struct lxc_conf *conf)
 #endif
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       if (conf->has_seccomp_notify) {
-               ret = seccomp_notif_get_fd(conf->seccomp_ctx);
+       if (conf->seccomp.notifier.wants_supervision) {
+               ret = seccomp_notif_get_fd(conf->seccomp.seccomp_ctx);
                if (ret < 0) {
                        errno = -ret;
                        return -1;
                }
 
-               conf->seccomp_notify_fd = ret;
+               conf->seccomp.notifier.notify_fd = ret;
                TRACE("Retrieved new seccomp listener fd %d", ret);
        }
 #endif
@@ -1270,24 +1272,23 @@ int lxc_seccomp_load(struct lxc_conf *conf)
        return 0;
 }
 
-void lxc_seccomp_free(struct lxc_conf *conf)
+void lxc_seccomp_free(struct lxc_seccomp *seccomp)
 {
-       free(conf->seccomp);
-       conf->seccomp = NULL;
+       free_disarm(seccomp->seccomp);
 
 #if HAVE_SCMP_FILTER_CTX
-       if (conf->seccomp_ctx) {
-               seccomp_release(conf->seccomp_ctx);
-               conf->seccomp_ctx = NULL;
+       if (seccomp->seccomp_ctx) {
+               seccomp_release(seccomp->seccomp_ctx);
+               seccomp->seccomp_ctx = NULL;
        }
 #endif
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       close_prot_errno_disarm(conf->seccomp_notify_fd);
-       close_prot_errno_disarm(conf->seccomp_notify_proxy_fd);
-       seccomp_notif_free(conf->seccomp_notify_req, conf->seccomp_notify_resp);
-       conf->seccomp_notify_req = NULL;
-       conf->seccomp_notify_resp = NULL;
+       close_prot_errno_disarm(seccomp->notifier.notify_fd);
+       close_prot_errno_disarm(seccomp->notifier.proxy_fd);
+       seccomp_notif_free(seccomp->notifier.req_buf, seccomp->notifier.rsp_buf);
+       seccomp->notifier.req_buf = NULL;
+       seccomp->notifier.rsp_buf = NULL;
 #endif
 }
 
@@ -1296,9 +1297,9 @@ 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);
+       close_prot_errno_disarm(handler->conf->seccomp.notifier.proxy_fd);
 
-       notify_fd = lxc_unix_connect(&handler->conf->seccomp_notify_proxy_addr);
+       notify_fd = lxc_unix_connect(&handler->conf->seccomp.notifier.proxy_addr);
        if (notify_fd < 0) {
                SYSERROR("Failed to reconnect to seccomp proxy");
                return -1;
@@ -1309,7 +1310,7 @@ static int seccomp_notify_reconnect(struct lxc_handler *handler)
                SYSERROR("Failed to set socket timeout");
                return -1;
        }
-       handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
+       handler->conf->seccomp.notifier.proxy_fd = move_fd(notify_fd);
        return 0;
 }
 #endif
@@ -1338,9 +1339,9 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
        ssize_t bytes;
        struct lxc_handler *hdlr = data;
        struct lxc_conf *conf = hdlr->conf;
-       struct seccomp_notif *req = conf->seccomp_notify_req;
-       struct seccomp_notif_resp *resp = conf->seccomp_notify_resp;
-       int listener_proxy_fd = conf->seccomp_notify_proxy_fd;
+       struct seccomp_notif *req = conf->seccomp.notifier.req_buf;
+       struct seccomp_notif_resp *resp = conf->seccomp.notifier.rsp_buf;
+       int listener_proxy_fd = conf->seccomp.notifier.proxy_fd;
        struct seccomp_notify_proxy_msg msg;
 
        if (listener_proxy_fd < 0) {
@@ -1390,3 +1391,113 @@ out:
        return -ENOSYS;
 #endif
 }
+
+void seccomp_conf_init(struct lxc_conf *conf)
+{
+       conf->seccomp.seccomp = NULL;
+#if HAVE_SCMP_FILTER_CTX
+       conf->seccomp.allow_nesting = 0;
+       memset(&conf->seccomp.seccomp_ctx, 0, sizeof(conf->seccomp.seccomp_ctx));
+#endif /* HAVE_SCMP_FILTER_CTX */
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       conf->seccomp.notifier.wants_supervision = false;
+       conf->seccomp.notifier.notify_fd = -EBADF;
+       conf->seccomp.notifier.proxy_fd = -EBADF;
+       memset(&conf->seccomp.notifier.proxy_addr, 0,
+              sizeof(conf->seccomp.notifier.proxy_addr));
+       conf->seccomp.notifier.req_buf = NULL;
+       conf->seccomp.notifier.rsp_buf = NULL;
+#endif
+}
+
+int lxc_seccomp_setup_notifier(struct lxc_seccomp *seccomp,
+                              struct lxc_epoll_descr *descr,
+                              struct lxc_handler *handler)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       if (seccomp->notifier.wants_supervision &&
+           seccomp->notifier.proxy_addr.sun_path[1] != '\0') {
+               __do_close_prot_errno int notify_fd = -EBADF;
+               int ret;
+
+               notify_fd = lxc_unix_connect(&seccomp->notifier.proxy_addr);
+               if (notify_fd < 0)
+                       return -1;
+
+               /* 30 second timeout */
+               ret = lxc_socket_set_timeout(notify_fd, 30, 30);
+               if (ret)
+                       return -1;
+
+               ret = lxc_mainloop_add_handler(descr,
+                                              seccomp->notifier.notify_fd,
+                                              seccomp_notify_handler, handler);
+               if (ret < 0) {
+                       ERROR("Failed to add seccomp notify handler for %d to mainloop",
+                             seccomp->notifier.notify_fd);
+                       return -1;
+               }
+
+               seccomp->notifier.proxy_fd = move_fd(notify_fd);
+       }
+#endif
+       return 0;
+}
+
+int lxc_seccomp_send_notifier_fd(struct lxc_seccomp *seccomp, int socket_fd)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       if (seccomp->notifier.wants_supervision) {
+               if (lxc_abstract_unix_send_fds(socket_fd,
+                                              &seccomp->notifier.notify_fd, 1,
+                                              NULL, 0) < 0)
+                       return -1;
+               close_prot_errno_disarm(seccomp->notifier.notify_fd);
+       }
+#endif
+       return 0;
+}
+
+int lxc_seccomp_recv_notifier_fd(struct lxc_seccomp *seccomp, int socket_fd)
+{
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       if (seccomp->notifier.wants_supervision) {
+               int ret;
+
+               ret = lxc_abstract_unix_recv_fds(socket_fd,
+                                                &seccomp->notifier.notify_fd,
+                                                1, NULL, 0);
+               if (ret < 0)
+                       return -1;
+
+               if (seccomp->notifier.proxy_fd >= 0) {
+                       ret = seccomp_notif_alloc(&seccomp->notifier.req_buf,
+                                                 &seccomp->notifier.rsp_buf);
+                       if (ret) {
+                               errno = ret;
+                               return -1;
+                       }
+               }
+       }
+#endif
+       return 0;
+}
+
+int lxc_seccomp_add_notifier(const char *name, const char *lxcpath,
+                            struct lxc_seccomp *seccomp)
+{
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+       if (seccomp->notifier.proxy_fd >= 0) {
+               int ret;
+
+               ret = lxc_cmd_seccomp_notify_add_listener(name, lxcpath,
+                                                         seccomp->notifier.notify_fd,
+                                                         -1, 0);
+               close_prot_errno_disarm(seccomp->notifier.notify_fd);
+               if (ret < 0)
+                       return -1;
+       }
+#endif
+       return 0;
+}
index b26d0ce7a49fe99c7cf27507706d6e7e10f1d887..a72970fdf19c662cdba94073feb39875b69ac2ef 100644 (file)
@@ -591,32 +591,9 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
                goto out_mainloop_console;
        }
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       if (handler->conf->has_seccomp_notify &&
-           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);
-               if (ret < 0) {
-                       ERROR("Failed to add seccomp notify handler for %d to mainloop",
-                             handler->conf->seccomp_notify_fd);
-                       goto out_mainloop_console;
-               }
-
-               handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
-       }
-#endif
+       ret = lxc_seccomp_setup_notifier(&handler->conf->seccomp, &descr, handler);
+       if (ret < 0)
+               goto out_mainloop_console;
 
        if (has_console) {
                struct lxc_terminal *console = &handler->conf->console;
@@ -1357,19 +1334,11 @@ static int do_start(void *data)
        if (ret < 0)
                goto out_warn_father;
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       if (handler->conf->has_seccomp_notify) {
-               ret = lxc_abstract_unix_send_fds(data_sock0,
-                                                &handler->conf->seccomp_notify_fd,
-                                                1, NULL, 0);
-               if (ret < 0) {
-                       SYSERROR("Failed to send seccomp notify fd to parent");
-                       goto out_warn_father;
-               }
-               close(handler->conf->seccomp_notify_fd);
-               handler->conf->seccomp_notify_fd = -EBADF;
+       ret = lxc_seccomp_send_notifier_fd(&handler->conf->seccomp, data_sock0);
+       if (ret < 0) {
+               SYSERROR("Failed to send seccomp notify fd to parent");
+               goto out_warn_father;
        }
-#endif
 
        ret = run_lxc_hooks(handler->name, "start", handler->conf, NULL);
        if (ret < 0) {
@@ -1932,25 +1901,11 @@ static int lxc_spawn(struct lxc_handler *handler)
                goto out_delete_net;
        }
 
-#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
-       if (handler->conf->has_seccomp_notify) {
-               ret = lxc_abstract_unix_recv_fds(handler->data_sock[1],
-                                                &handler->conf->seccomp_notify_fd,
-                                                1, NULL, 0);
-               if (ret < 0) {
-                       SYSERROR("Failed to receive seccomp notify fd from child");
-                       goto out_delete_net;
-               }
-
-               ret = seccomp_notif_alloc(&handler->conf->seccomp_notify_req,
-                                         &handler->conf->seccomp_notify_resp);
-               if (ret) {
-                       errno = ret;
-                       ret = -1;
-                       goto out_delete_net;
-               }
+       ret = lxc_seccomp_recv_notifier_fd(&handler->conf->seccomp, data_sock1);
+       if (ret < 0) {
+               SYSERROR("Failed to receive seccomp notify fd from child");
+               goto out_delete_net;
        }
-#endif
 
        ret = handler->ops->post_start(handler, handler->data);
        if (ret < 0)
index f7e9dc8294ba04a9ea908c2f29d8350d6c92882a..309212e9c93ac0e83a9e31d7190285802eff409b 100644 (file)
@@ -25,7 +25,8 @@ lxc_test_locktests_SOURCES = locktests.c
 lxc_test_lxcpath_SOURCES = lxcpath.c
 lxc_test_may_control_SOURCES = may_control.c
 lxc_test_mount_injection_SOURCES = mount_injection.c lxctest.h
-lxc_test_parse_config_file_SOURCES = parse_config_file.c lxctest.h
+lxc_test_parse_config_file_SOURCES = parse_config_file.c \
+                                    lxctest.h
 lxc_test_raw_clone_SOURCES = lxc_raw_clone.c \
                             lxctest.h \
                             ../lxc/namespace.c ../lxc/namespace.h \
@@ -57,6 +58,11 @@ if ENABLE_APPARMOR
 AM_CFLAGS += -DHAVE_APPARMOR
 endif
 
+if ENABLE_SECCOMP
+AM_CFLAGS += -DHAVE_SECCOMP \
+            $(SECCOMP_CFLAGS)
+endif
+
 if ENABLE_SELINUX
 AM_CFLAGS += -DHAVE_SELINUX
 endif
index b8b71c8e1e5105382bf853f0f3c4b84c270f1f04..c265cd1d9f335903bfbe9d15097e6f542b9f4b51 100644 (file)
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <libgen.h>
 
+#include "conf.h"
 #include "confile_utils.h"
 #include "lxc/state.h"
 #include "lxctest.h"