From: Christian Brauner Date: Mon, 29 Apr 2019 08:16:01 +0000 (+0200) Subject: seccomp: cleanup X-Git-Tag: lxc-3.2.0~88^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c3e3c21a10fcef31f484f7afb7807824eb4dccab;p=thirdparty%2Flxc.git seccomp: cleanup 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 --- diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c index 328f891f0..275430a52 100644 --- a/src/lxc/af_unix.c +++ b/src/lxc/af_unix.c @@ -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; /* diff --git a/src/lxc/attach.c b/src/lxc/attach.c index ac0450187..331434b26 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -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 diff --git a/src/lxc/commands.c b/src/lxc/commands.c index e42990465..90e3c5863 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -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, diff --git a/src/lxc/conf.c b/src/lxc/conf.c index db00c70e9..ec9543f74 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index f7b8e9724..2664a1527 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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 */ diff --git a/src/lxc/confile.c b/src/lxc/confile.c index da5e45ce3..efbac0c3d 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -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; } diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index e16639d48..98f86a24e 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -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) diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index 2bd327114..e2e788993 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -31,7 +31,8 @@ #include -#if HAVE_DECL_SECCOMP_NOTIF_GET_FD +#ifdef SCMP_ACT_USER_NOTIF +#include #include #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; diff --git a/src/lxc/lxcseccomp.h b/src/lxc/lxcseccomp.h index 530fffd80..aafe09f12 100644 --- a/src/lxc/lxcseccomp.h +++ b/src/lxc/lxcseccomp.h @@ -24,21 +24,86 @@ #ifndef __LXC_LXCSECCOMP_H #define __LXC_LXCSECCOMP_H +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif #include #ifdef HAVE_SECCOMP +#include #include #endif +#if HAVE_DECL_SECCOMP_NOTIF_GET_FD +#include +#include +#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 */ diff --git a/src/lxc/memory_utils.h b/src/lxc/memory_utils.h index c1dafb441..b5220c189 100644 --- a/src/lxc/memory_utils.h +++ b/src/lxc/memory_utils.h @@ -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); diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 287da564d..a63b6d69f 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -32,10 +32,12 @@ #include #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; +} diff --git a/src/lxc/start.c b/src/lxc/start.c index b26d0ce7a..a72970fdf 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -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) diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index f7e9dc829..309212e9c 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -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 diff --git a/src/tests/parse_config_file.c b/src/tests/parse_config_file.c index b8b71c8e1..c265cd1d9 100644 --- a/src/tests/parse_config_file.c +++ b/src/tests/parse_config_file.c @@ -28,6 +28,7 @@ #include #include +#include "conf.h" #include "confile_utils.h" #include "lxc/state.h" #include "lxctest.h"