From 86ce1da153fddccc5ae6c1ab86447a96e2520d93 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Thu, 25 Apr 2019 14:51:51 +0200 Subject: [PATCH] confile: add lxc.seccomp.notify.proxy Signed-off-by: Christian Brauner --- src/lxc/af_unix.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/af_unix.h | 5 ++++ src/lxc/conf.c | 1 + src/lxc/conf.h | 1 + src/lxc/confile.c | 50 +++++++++++++++++++++++++++++++++ src/lxc/start.c | 15 +++++++++- 6 files changed, 141 insertions(+), 1 deletion(-) diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c index 06700fac1..328f891f0 100644 --- a/src/lxc/af_unix.c +++ b/src/lxc/af_unix.c @@ -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; +} diff --git a/src/lxc/af_unix.h b/src/lxc/af_unix.h index f2c2fdcc6..3ae595498 100644 --- a/src/lxc/af_unix.h +++ b/src/lxc/af_unix.h @@ -25,6 +25,8 @@ #define __LXC_AF_UNIX_H #include +#include +#include /* 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 */ diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 453763243..db00c70e9 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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 diff --git a/src/lxc/conf.h b/src/lxc/conf.h index f00f477c3..f7b8e9724 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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 diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 8f94635d1..da5e45ce3 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -46,6 +46,7 @@ #include #include +#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) { diff --git a/src/lxc/start.c b/src/lxc/start.c index b1b4a3af7..6d5913af6 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -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 -- 2.47.2