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: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 41cd8a8d
......@@ -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;
/*
......
......@@ -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
......
......@@ -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,
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -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;
......
......@@ -24,21 +24,86 @@
#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 */
......@@ -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);
......
......@@ -32,10 +32,12 @@
#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;
}
......@@ -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)
......
......@@ -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
......
......@@ -28,6 +28,7 @@
#include <unistd.h>
#include <libgen.h>
#include "conf.h"
#include "confile_utils.h"
#include "lxc/state.h"
#include "lxctest.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment