OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $SECCOMP_CFLAGS"
AC_CHECK_TYPES([scmp_filter_ctx], [], [], [[#include <seccomp.h>]])
+AC_CHECK_DECLS([seccomp_notif_get_fd], [], [], [[#include <seccomp.h>]])
AC_CHECK_DECLS([seccomp_syscall_resolve_name_arch], [], [], [[#include <seccomp.h>]])
CFLAGS="$OLD_CFLAGS"
struct iovec iov;
struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
- size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int));
+ size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) +
+ CMSG_SPACE(num_recvfds * sizeof(int));
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
if (ret <= 0)
goto out;
- cmsg = CMSG_FIRSTHDR(&msg);
-
- memset(recvfds, -1, num_recvfds * sizeof(int));
- if (cmsg && cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
- cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
- memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
+ /*
+ * If SO_PASSCRED is set we will always get a ucred message.
+ */
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_type != SCM_RIGHTS)
+ continue;
+
+ memset(recvfds, -1, num_recvfds * sizeof(int));
+ if (cmsg &&
+ cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
+ cmsg->cmsg_level == SOL_SOCKET)
+ memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
+ break;
+ }
out:
return ret;
if (init_ctx->container && init_ctx->container->lxc_conf &&
init_ctx->container->lxc_conf->seccomp) {
- ret = lxc_seccomp_load(init_ctx->container->lxc_conf);
+ struct lxc_conf *conf = init_ctx->container->lxc_conf;
+
+ ret = lxc_seccomp_load(conf);
if (ret < 0)
goto on_error;
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
}
close(payload->ipc_socket);
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;
+
+ 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
+
/* We're done, the child process should now execute whatever it
* is that the user requested. The parent can now track it with
* waitpid() or similar.
#include "log.h"
#include "lxc.h"
#include "lxclock.h"
+#include "lxcseccomp.h"
#include "mainloop.h"
#include "memory_utils.h"
#include "monitor.h"
[LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
[LXC_CMD_CONSOLE_LOG] = "console_log",
[LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
+ [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener",
};
if (cmd >= LXC_CMD_MAX)
if (ret < 0 || (size_t)ret != sizeof(cmd->req))
return -1;
- if (cmd->req.datalen <= 0)
- return move_fd(client_fd);
+ if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
+ int notify_fd = PTR_TO_INT(cmd->req.data);
+ ret = lxc_abstract_unix_send_fds(client_fd, ¬ify_fd, 1, NULL, 0);
+ if (ret <= 0)
+ return -1;
+ } else {
+ if (cmd->req.datalen <= 0)
+ return move_fd(client_fd);
- errno = EMSGSIZE;
- ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
- cmd->req.datalen, MSG_NOSIGNAL);
- if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
- return -1;
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
+ cmd->req.datalen, MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
+ return -1;
+ }
return move_fd(client_fd);
}
}
static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
intmax_t pid = handler->pid;
}
static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->ns_clone_flags) };
}
static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
const char *path;
struct lxc_cmd_rsp rsp;
}
static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
__do_free char *cidata = NULL;
int cilen;
}
static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) };
}
static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp;
int stopsignal = SIGKILL;
}
static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
/* should never be called */
return -1;
}
static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
int masterfd, ret;
struct lxc_cmd_rsp rsp;
}
static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp;
}
static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp;
}
static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
int ret;
struct lxc_cmd_rsp rsp = {0};
}
static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
struct lxc_cmd_rsp rsp;
uint64_t buffer_size = handler->conf->console.buffer_size;
}
static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
int ret;
lxc_state_t state = PTR_TO_INT(req->data);
return 1;
}
+int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
+ int fd,
+ /* unused */ unsigned int command,
+ /* unused */ unsigned int flags)
+{
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ int ret, stopped;
+ struct lxc_cmd_rr cmd = {
+ .req = {
+ .cmd = LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
+ .data = INT_TO_PTR(fd),
+ },
+ };
+
+ ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
+ if (ret < 0) {
+ SYSERROR("Failed to execute command");
+ return -1;
+ }
+
+ return cmd.rsp.ret;
+#else
+ return minus_one_set_errno(ENOSYS);
+#endif
+}
+
+static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
+ struct lxc_cmd_req *req,
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
+{
+ struct lxc_cmd_rsp rsp = {0};
+ int ret;
+
+#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)
+ goto reap_client_fd;
+
+ ret = lxc_mainloop_add_handler(descr, notify_fd, seccomp_notify_handler,
+ handler);
+ 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;
+}
+
static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
- struct lxc_handler *handler)
+ struct lxc_handler *handler,
+ struct lxc_epoll_descr *descr)
{
- typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *);
+ typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
+ struct lxc_epoll_descr *);
callback cb[LXC_CMD_MAX] = {
- [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
- [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
- [LXC_CMD_STOP] = lxc_cmd_stop_callback,
- [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
- [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
- [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
- [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
- [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
- [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
- [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
- [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
- [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
- [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
+ [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
+ [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
+ [LXC_CMD_STOP] = lxc_cmd_stop_callback,
+ [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
+ [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
+ [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
+ [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
+ [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
+ [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
+ [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
+ [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
+ [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
+ [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
+ [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback,
};
if (req->cmd >= LXC_CMD_MAX) {
ERROR("Undefined command id %d", req->cmd);
return -1;
}
- return cb[req->cmd](fd, req, handler);
+ return cb[req->cmd](fd, req, handler, descr);
}
static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
- struct lxc_epoll_descr *descr,
- const lxc_cmd_t cmd)
+ struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
{
struct lxc_list *cur, *next;
lxc_terminal_free(handler->conf, fd);
lxc_mainloop_del_handler(descr, fd);
- if (cmd != LXC_CMD_ADD_STATE_CLIENT) {
- close(fd);
- return;
- }
-
- lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
- struct lxc_state_client *client = cur->elem;
-
- if (client->clientfd != fd)
- continue;
- /* kick client from list */
- lxc_list_del(cur);
- close(client->clientfd);
- free(cur->elem);
- free(cur);
- /* No need to walk the whole list. If we found the state client
- * fd there can't be a second one.
- */
+ switch (cmd) {
+ case LXC_CMD_ADD_STATE_CLIENT:
+ lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
+ struct lxc_state_client *client = cur->elem;
+
+ if (client->clientfd != fd)
+ continue;
+
+ /* kick client from list */
+ lxc_list_del(cur);
+ close(client->clientfd);
+ free(cur->elem);
+ free(cur);
+ /* No need to walk the whole list. If we found the state
+ * client fd there can't be a second one.
+ */
+ break;
+ }
break;
+ default:
+ close(fd);
}
}
req.data = reqdata;
}
- ret = lxc_cmd_process(fd, &req, handler);
+ ret = lxc_cmd_process(fd, &req, handler, descr);
if (ret) {
/* This is not an error, but only a request to close fd. */
ret = LXC_MAINLOOP_CONTINUE;
LXC_CMD_ADD_STATE_CLIENT,
LXC_CMD_CONSOLE_LOG,
LXC_CMD_SERVE_STATE_CLIENTS,
+ LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
LXC_CMD_MAX,
} lxc_cmd_t;
extern int lxc_try_cmd(const char *name, const char *lxcpath);
extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
struct lxc_console_log *log);
+extern int lxc_cmd_seccomp_notify_add_listener(const char *name,
+ const char *lxcpath,
+ int fd,
+ /* unused */ unsigned int command,
+ /* unused */ unsigned int flags);
#endif /* __commands_h */
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;
+ 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;
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 seccomp_notif *seccomp_notify_req;
+ struct seccomp_notif_resp *seccomp_notify_resp;
#endif
int maincmd_fd;
unsigned int autodev; /* if 1, mount and fill a /dev at start */
return ret;
}
+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);
+
+ switch (cmd) {
+ case LXC_SECCOMP_NOTIFY_GET_FD:
+ if (fd)
+ return minus_one_set_errno(EINVAL);
+
+ return c->lxc_conf->seccomp_notify_fd;
+ }
+
+ return minus_one_set_errno(EINVAL);
+#else
+ return minus_one_set_errno(ENOSYS);
+#endif
+}
+
+WRAP_API_2(int, lxcapi_seccomp_notify, unsigned int, int)
+
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
{
struct lxc_container *c;
c->console_log = lxcapi_console_log;
c->mount = lxcapi_mount;
c->umount = lxcapi_umount;
+ c->seccomp_notify = lxcapi_seccomp_notify;
return c;
#include <lxc/attach_options.h>
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+#include <seccomp.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
int version;
};
+enum {
+ LXC_SECCOMP_NOTIFY_GET_FD = 0,
+ LXC_SECCOMP_NOTIFY_MAX,
+};
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+struct seccomp_notify_proxy_msg {
+ uint32_t version;
+ struct seccomp_notif req;
+ struct seccomp_notif_resp resp;
+ pid_t monitor_pid;
+ pid_t init_pid;
+};
+#endif
+
/*!
* An LXC container.
*
*/
int (*umount)(struct lxc_container *c, const char *target,
unsigned long mountflags, struct lxc_mount *mnt);
+
+ int (*seccomp_notify)(struct lxc_container *c, unsigned int cmd, int fd);
};
/*!
#ifndef __LXC_LXCSECCOMP_H
#define __LXC_LXCSECCOMP_H
+#include <errno.h>
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
+
#include "conf.h"
#ifdef HAVE_SECCOMP
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);
+
#else
static inline int lxc_seccomp_load(struct lxc_conf *conf)
{
free(conf->seccomp);
conf->seccomp = NULL;
}
+static inline int seccomp_notify_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ return -ENOSYS;
+}
#endif
#endif
__internal_fd__; \
})
+#define minus_one_set_errno(__errno__) \
+ ({ \
+ errno = __errno__; \
+ -1; \
+ })
+
#endif /* __LXC_MACRO_H */
#include "config.h"
#include "log.h"
+#include "lxccontainer.h"
#include "lxcseccomp.h"
+#include "memory_utils.h"
#include "utils.h"
#ifdef __MIPSEL__
return "trap";
case SCMP_ACT_ERRNO(0):
return "errno";
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ case SCMP_ACT_USER_NOTIF:
+ return "notify";
+#endif
}
return "invalid action";
ret_action = SCMP_ACT_ALLOW;
} else if (strncmp(line, "trap", 4) == 0) {
ret_action = SCMP_ACT_TRAP;
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ } else if (strncmp(line, "notify", 6) == 0) {
+ ret_action = SCMP_ACT_USER_NOTIF;
+#endif
} else if (line[0]) {
ERROR("Unrecognized seccomp action \"%s\"", line);
return -2;
goto bad_rule;
}
+#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,
+ SCMP_FLTATR_NEW_LISTENER, 1);
+ if (ret)
+ goto bad_rule;
+
+ conf->has_seccomp_notify = true;
+ TRACE("Set SCMP_FLTATR_NEW_LISTENER attribute");
+ }
+#endif
+
if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line,
conf->seccomp_ctx, &rule))
goto bad_rule;
}
#endif
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ if (conf->has_seccomp_notify) {
+ ret = seccomp_notif_get_fd(conf->seccomp_ctx);
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+
+ conf->seccomp_notify_fd = ret;
+ TRACE("Retrieved new seccomp listener fd %d", ret);
+ }
+#endif
+
return 0;
}
conf->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;
+#endif
+}
+
+int seccomp_notify_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ int ret;
+ 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_notify_proxy_msg msg;
+
+ if (listener_proxy_fd < 0)
+ return minus_one_set_errno(EINVAL);
+
+ ret = seccomp_notif_receive(fd, req);
+ if (ret)
+ return minus_one_set_errno(-ret);
+
+ memcpy(&msg.req, req, sizeof(msg.req));
+ msg.monitor_pid = hdlr->monitor_pid;
+ msg.init_pid = hdlr->pid;
+
+ ret = lxc_send_nointr(listener_proxy_fd, &msg, sizeof(msg), MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)sizeof(msg))
+ return -1;
+
+ ret = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);
+ if (ret != (ssize_t)sizeof(msg))
+ return -1;
+
+ memcpy(resp, &msg.resp, sizeof(*resp));
+
+ ret = seccomp_notif_send_resp(fd, resp);
+ if (ret)
+ return minus_one_set_errno(-ret);
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
}
goto out_mainloop_console;
}
+#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
+ if (handler->conf->has_seccomp_notify &&
+ handler->conf->seccomp_notify_proxy_fd >= 0) {
+ 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;
+ }
+ }
+#endif
+
if (has_console) {
struct lxc_terminal *console = &handler->conf->console;
static int do_start(void *data)
{
+ struct lxc_handler *handler = data;
+ __do_close_prot_errno int data_sock0 = handler->data_sock[0],
+ data_sock1 = handler->data_sock[1];
int ret;
char path[PATH_MAX];
uid_t new_uid;
uid_t nsuid = 0;
gid_t nsgid = 0;
int devnull_fd = -1;
- struct lxc_handler *handler = data;
lxc_sync_fini_parent(handler);
/* Setup the container, ip, names, utsname, ... */
ret = lxc_setup(handler);
- close(handler->data_sock[1]);
- close(handler->data_sock[0]);
if (ret < 0) {
ERROR("Failed to setup container \"%s\"", handler->name);
goto out_warn_father;
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;
+ }
+#endif
+
ret = run_lxc_hooks(handler->name, "start", handler->conf, NULL);
if (ret < 0) {
ERROR("Failed to run lxc.hook.start for container \"%s\"",
*/
static int lxc_spawn(struct lxc_handler *handler)
{
+ __do_close_prot_errno int data_sock0 = -EBADF, data_sock1 = -EBADF;
int i, ret;
char pidstr[20];
bool wants_to_map_ids;
handler->data_sock);
if (ret < 0)
goto out_sync_fini;
+ data_sock0 = handler->data_sock[0];
+ data_sock1 = handler->data_sock[1];
ret = resolve_clone_flags(handler);
if (ret < 0)
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;
+ }
+ }
+#endif
+
ret = handler->ops->post_start(handler, handler->data);
if (ret < 0)
goto out_abort;
ERROR("Failed to spawn container \"%s\"", name);
goto out_detach_blockdev;
}
- /* close parent side of data socket */
- close(handler->data_sock[0]);
- handler->data_sock[0] = -1;
- close(handler->data_sock[1]);
- handler->data_sock[1] = -1;
handler->conf->reboot = REBOOT_NONE;