[lxc-devel] [lxc/master] seccomp: cleanup

brauner on Github lxc-bot at linuxcontainers.org
Mon Apr 29 09:51:09 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 364 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190429/15353f83/attachment-0001.bin>
-------------- next part --------------
From 62a3cdcd00c41094dd471aa8640cd2b4d6dd7859 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Mon, 29 Apr 2019 10:16:01 +0200
Subject: [PATCH] seccomp: cleanup

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/af_unix.c             |  22 ++++-
 src/lxc/attach.c              |  42 +++-----
 src/lxc/commands.c            |  40 ++++----
 src/lxc/conf.c                |   9 +-
 src/lxc/conf.h                |  15 +--
 src/lxc/confile.c             |  28 +++---
 src/lxc/lxccontainer.c        |   2 +-
 src/lxc/lxcseccomp.h          |  83 +++++++++++++++-
 src/lxc/seccomp.c             | 174 ++++++++++++++++++++++++++--------
 src/lxc/start.c               |  67 +++----------
 src/tests/Makefile.am         |   8 +-
 src/tests/parse_config_file.c |   1 +
 12 files changed, 300 insertions(+), 191 deletions(-)

diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c
index 328f891f0b..275430a52a 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 ac0450187b..4b4a925175 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,21 @@ 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;
+		if (conf->seccomp.notifier.notify_fd >= 0) {
 			TRACE("Retrieved seccomp listener fd %d from child",
-			      conf->seccomp_notify_fd);
+			      conf->seccomp.notifier.notify_fd);
 			ret = lxc_cmd_seccomp_notify_add_listener(name, lxcpath,
-								  conf->seccomp_notify_fd,
+								  conf->seccomp.notifier.notify_fd,
 								  -1, 0);
-			close_prot_errno_disarm(conf->seccomp_notify_fd);
 			if (ret < 0)
 				goto close_mainloop;
+			TRACE("Added seccomp listener fd %d to mainloop",
+			      conf->seccomp.notifier.notify_fd);
+			close_prot_errno_disarm(conf->seccomp.notifier.notify_fd);
 		}
-#endif
 
 		/* 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 e429904652..69c41a8eb6 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -1079,44 +1079,40 @@ static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
 							struct lxc_handler *handler,
 							struct lxc_epoll_descr *descr)
 {
-	struct lxc_cmd_rsp rsp = {0};
 	int ret;
+	struct lxc_cmd_rsp rsp = {0};
 
 #if HAVE_DECL_SECCOMP_NOTIF_GET_FD
 	__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:
 #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;
+out:
+	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 db00c70e99..89d29233fe 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;
 }
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index f7b8e97248..b7a27687d6 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,18 +296,8 @@ 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;
+#ifdef HAVE_SECCOMP
+	struct lxc_seccomp seccomp;
 #endif
 	int maincmd_fd;
 	unsigned int autodev;  /* if 1, mount and fill a /dev at start */
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index da5e45ce3c..06019620cf 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -783,10 +783,10 @@ static int set_config_seccomp_allow_nesting(const char *key, const char *value,
 	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;
@@ -805,7 +805,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 +817,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,7 +3726,7 @@ 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);
+	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,
@@ -3734,9 +3734,9 @@ static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inle
 {
 #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]);
+				(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 +3745,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,7 +4328,7 @@ 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;
+	c->seccomp.allow_nesting = 0;
 	return 0;
 }
 
@@ -4336,8 +4336,8 @@ 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));
+	memset(&c->seccomp.notifier.proxy_addr, 0,
+	       sizeof(c->seccomp.notifier.proxy_addr));
 	return 0;
 #else
 	return minus_one_set_errno(ENOSYS);
@@ -4347,8 +4347,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 e16639d485..66a12263aa 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -5238,7 +5238,7 @@ 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 c->lxc_conf->seccomp.notifier.notify_fd;
 	}
 
 	return minus_one_set_errno(EINVAL);
diff --git a/src/lxc/lxcseccomp.h b/src/lxc/lxcseccomp.h
index 530fffd80a..5d0df282d0 100644
--- a/src/lxc/lxcseccomp.h
+++ b/src/lxc/lxcseccomp.h
@@ -24,21 +24,71 @@
 #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"
+
+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;
+};
+#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 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);
+
+#else /* HAVE_SECCOMP */
+
+struct lxc_seccomp {
+	char *seccomp;
+};
 
-#else
 static inline int lxc_seccomp_load(struct lxc_conf *conf)
 {
 	return 0;
@@ -51,14 +101,37 @@ static inline int lxc_read_seccomp_config(struct lxc_conf *conf)
 
 static inline void lxc_seccomp_free(struct lxc_conf *conf)
 {
-	free(conf->seccomp);
-	conf->seccomp = NULL;
+	free(conf->seccomp.seccomp);
+	conf->seccomp.seccomp = NULL;
 }
 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;
+}
+
+#endif /* HAVE_SECCOMP */
+#endif /* __LXC_LXCSECCOMP_H */
diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c
index 287da564d2..12f47a0d53 100644
--- a/src/lxc/seccomp.c
+++ b/src/lxc/seccomp.c
@@ -36,6 +36,7 @@
 #include "log.h"
 #include "lxccontainer.h"
 #include "lxcseccomp.h"
+#include "mainloop.h"
 #include "memory_utils.h"
 #include "utils.h"
 
@@ -63,7 +64,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 +737,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 +751,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 +942,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 +995,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 +1011,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 +1027,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 +1129,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 +1168,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 +1176,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 +1189,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 +1200,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 +1223,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 +1246,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 +1256,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
@@ -1272,22 +1273,22 @@ int lxc_seccomp_load(struct lxc_conf *conf)
 
 void lxc_seccomp_free(struct lxc_conf *conf)
 {
-	free(conf->seccomp);
-	conf->seccomp = NULL;
+	free(conf->seccomp.seccomp);
+	conf->seccomp.seccomp = NULL;
 
 #if HAVE_SCMP_FILTER_CTX
-	if (conf->seccomp_ctx) {
-		seccomp_release(conf->seccomp_ctx);
-		conf->seccomp_ctx = NULL;
+	if (conf->seccomp.seccomp_ctx) {
+		seccomp_release(conf->seccomp.seccomp_ctx);
+		conf->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(conf->seccomp.notifier.notify_fd);
+	close_prot_errno_disarm(conf->seccomp.notifier.proxy_fd);
+	seccomp_notif_free(conf->seccomp.notifier.req_buf, conf->seccomp.notifier.rsp_buf);
+	conf->seccomp.notifier.req_buf = NULL;
+	conf->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,94 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
 	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;
+}
diff --git a/src/lxc/start.c b/src/lxc/start.c
index b26d0ce7a4..a72970fdf1 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 f7e9dc8294..309212e9c9 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 b8b71c8e1e..c265cd1d9f 100644
--- a/src/tests/parse_config_file.c
+++ b/src/tests/parse_config_file.c
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <libgen.h>
 
+#include "conf.h"
 #include "confile_utils.h"
 #include "lxc/state.h"
 #include "lxctest.h"


More information about the lxc-devel mailing list