mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-17 18:31:41 +00:00
Merge pull request #2947 from brauner/2019-04-18/seccomp_trap
seccomp: SECCOMP_RET_USER_NOTIF support
This commit is contained in:
commit
a82463a071
@ -363,6 +363,7 @@ AM_COND_IF([ENABLE_CAP],
|
|||||||
OLD_CFLAGS="$CFLAGS"
|
OLD_CFLAGS="$CFLAGS"
|
||||||
CFLAGS="$CFLAGS $SECCOMP_CFLAGS"
|
CFLAGS="$CFLAGS $SECCOMP_CFLAGS"
|
||||||
AC_CHECK_TYPES([scmp_filter_ctx], [], [], [[#include <seccomp.h>]])
|
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>]])
|
AC_CHECK_DECLS([seccomp_syscall_resolve_name_arch], [], [], [[#include <seccomp.h>]])
|
||||||
CFLAGS="$OLD_CFLAGS"
|
CFLAGS="$OLD_CFLAGS"
|
||||||
|
|
||||||
|
@ -1873,8 +1873,27 @@ dev/null proc/kcore none bind,relative 0 0
|
|||||||
2
|
2
|
||||||
blacklist
|
blacklist
|
||||||
mknod errno 0
|
mknod errno 0
|
||||||
|
ioctl notify
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Specifying "errno" as action will cause LXC to register a seccomp filter
|
||||||
|
that will cause a specific errno to be returned ot the caller. The errno
|
||||||
|
value can be specified after the "errno" action word.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Specifying "notify" as action will cause LXC to register a seccomp
|
||||||
|
listener and retrieve a listener file descriptor from the kernel. When a
|
||||||
|
syscall is made that is registered as "notify" the kernel will generate a
|
||||||
|
poll event and send a message over the file descriptor. The caller can
|
||||||
|
read this message, inspect the syscalls including its arguments. Based on
|
||||||
|
this information the caller is expected to send back a message informing
|
||||||
|
the kernel which action to take. Until that message is sent the kernel
|
||||||
|
will block the calling process. The format of the messages to read and
|
||||||
|
sent is documented in seccomp itself.
|
||||||
|
</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
@ -1900,6 +1919,20 @@ dev/null proc/kcore none bind,relative 0 0
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>lxc.seccomp.notify.proxy</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specify a unix socket to which LXC will connect and forward
|
||||||
|
seccomp events to. The path must by in the form
|
||||||
|
unix:/path/to/socket or unix:@socket. The former specifies a
|
||||||
|
path-bound unix domain socket while the latter specifies an
|
||||||
|
abstract unix domain socket.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
|
@ -201,7 +201,8 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
|
|||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct cmsghdr *cmsg = NULL;
|
struct cmsghdr *cmsg = NULL;
|
||||||
char buf[1] = {0};
|
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(&msg, 0, sizeof(msg));
|
||||||
memset(&iov, 0, sizeof(iov));
|
memset(&iov, 0, sizeof(iov));
|
||||||
@ -224,12 +225,20 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
|
|||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
cmsg = CMSG_FIRSTHDR(&msg);
|
/*
|
||||||
|
* 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));
|
memset(recvfds, -1, num_recvfds * sizeof(int));
|
||||||
if (cmsg && cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
|
if (cmsg &&
|
||||||
cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
|
cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
|
||||||
memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
|
cmsg->cmsg_level == SOL_SOCKET)
|
||||||
|
memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
@ -307,3 +316,73 @@ int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size)
|
|||||||
out:
|
out:
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#define __LXC_AF_UNIX_H
|
#define __LXC_AF_UNIX_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
/* does not enforce \0-termination */
|
/* does not enforce \0-termination */
|
||||||
extern int lxc_abstract_unix_open(const char *path, int type, int flags);
|
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);
|
void *data, size_t size);
|
||||||
extern int lxc_abstract_unix_send_credential(int fd, 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_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 */
|
#endif /* __LXC_AF_UNIX_H */
|
||||||
|
@ -43,6 +43,7 @@ static char *api_extensions[] = {
|
|||||||
"cgroup_relative",
|
"cgroup_relative",
|
||||||
"mount_injection_file",
|
"mount_injection_file",
|
||||||
"seccomp_allow_nesting",
|
"seccomp_allow_nesting",
|
||||||
|
"seccomp_notify",
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions);
|
static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions);
|
||||||
|
@ -853,11 +853,26 @@ static int attach_child_main(struct attach_clone_payload *payload)
|
|||||||
|
|
||||||
if (init_ctx->container && init_ctx->container->lxc_conf &&
|
if (init_ctx->container && init_ctx->container->lxc_conf &&
|
||||||
init_ctx->container->lxc_conf->seccomp) {
|
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)
|
if (ret < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
TRACE("Loaded seccomp profile");
|
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);
|
close(payload->ipc_socket);
|
||||||
@ -1311,6 +1326,25 @@ int lxc_attach(const char *name, const char *lxcpath,
|
|||||||
TRACE("Sent LSM label file descriptor %d to child", labelfd);
|
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
|
/* We're done, the child process should now execute whatever it
|
||||||
* is that the user requested. The parent can now track it with
|
* is that the user requested. The parent can now track it with
|
||||||
* waitpid() or similar.
|
* waitpid() or similar.
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "lxc.h"
|
#include "lxc.h"
|
||||||
#include "lxclock.h"
|
#include "lxclock.h"
|
||||||
|
#include "lxcseccomp.h"
|
||||||
#include "mainloop.h"
|
#include "mainloop.h"
|
||||||
#include "memory_utils.h"
|
#include "memory_utils.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
@ -97,6 +98,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
|
|||||||
[LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
|
[LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
|
||||||
[LXC_CMD_CONSOLE_LOG] = "console_log",
|
[LXC_CMD_CONSOLE_LOG] = "console_log",
|
||||||
[LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
|
[LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
|
||||||
|
[LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cmd >= LXC_CMD_MAX)
|
if (cmd >= LXC_CMD_MAX)
|
||||||
@ -244,14 +246,21 @@ static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
|
|||||||
if (ret < 0 || (size_t)ret != sizeof(cmd->req))
|
if (ret < 0 || (size_t)ret != sizeof(cmd->req))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (cmd->req.datalen <= 0)
|
if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
|
||||||
return move_fd(client_fd);
|
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;
|
errno = EMSGSIZE;
|
||||||
ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
|
ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
|
||||||
cmd->req.datalen, MSG_NOSIGNAL);
|
cmd->req.datalen, MSG_NOSIGNAL);
|
||||||
if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
|
if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return move_fd(client_fd);
|
return move_fd(client_fd);
|
||||||
}
|
}
|
||||||
@ -373,7 +382,8 @@ pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
intmax_t pid = handler->pid;
|
||||||
|
|
||||||
@ -407,7 +417,8 @@ int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
|
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) };
|
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->ns_clone_flags) };
|
||||||
|
|
||||||
@ -457,7 +468,8 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
const char *path;
|
||||||
struct lxc_cmd_rsp rsp;
|
struct lxc_cmd_rsp rsp;
|
||||||
@ -509,7 +521,8 @@ char *lxc_cmd_get_config_item(const char *name, const char *item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
__do_free char *cidata = NULL;
|
||||||
int cilen;
|
int cilen;
|
||||||
@ -575,7 +588,8 @@ int lxc_cmd_get_state(const char *name, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
|
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) };
|
struct lxc_cmd_rsp rsp = { .data = INT_TO_PTR(handler->state) };
|
||||||
|
|
||||||
@ -622,7 +636,8 @@ int lxc_cmd_stop(const char *name, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
struct lxc_cmd_rsp rsp;
|
||||||
int stopsignal = SIGKILL;
|
int stopsignal = SIGKILL;
|
||||||
@ -665,7 +680,8 @@ int lxc_cmd_terminal_winch(const char *name, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
|
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 */
|
/* should never be called */
|
||||||
return -1;
|
return -1;
|
||||||
@ -720,7 +736,8 @@ int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
int masterfd, ret;
|
||||||
struct lxc_cmd_rsp rsp;
|
struct lxc_cmd_rsp rsp;
|
||||||
@ -773,7 +790,8 @@ char *lxc_cmd_get_name(const char *hashed_sock_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
struct lxc_cmd_rsp rsp;
|
||||||
|
|
||||||
@ -811,7 +829,8 @@ char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
struct lxc_cmd_rsp rsp;
|
||||||
|
|
||||||
@ -872,7 +891,8 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
int ret;
|
||||||
struct lxc_cmd_rsp rsp = {0};
|
struct lxc_cmd_rsp rsp = {0};
|
||||||
@ -943,7 +963,8 @@ int lxc_cmd_console_log(const char *name, const char *lxcpath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
struct lxc_cmd_rsp rsp;
|
||||||
uint64_t buffer_size = handler->conf->console.buffer_size;
|
uint64_t buffer_size = handler->conf->console.buffer_size;
|
||||||
@ -1002,7 +1023,8 @@ int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
|
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;
|
int ret;
|
||||||
lxc_state_t state = PTR_TO_INT(req->data);
|
lxc_state_t state = PTR_TO_INT(req->data);
|
||||||
@ -1025,62 +1047,138 @@ reap_client_fd:
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
|
int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
|
||||||
struct lxc_handler *handler)
|
int fd,
|
||||||
|
/* unused */ unsigned int command,
|
||||||
|
/* unused */ unsigned int flags)
|
||||||
{
|
{
|
||||||
typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *);
|
|
||||||
|
#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_epoll_descr *descr)
|
||||||
|
{
|
||||||
|
typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
|
||||||
|
struct lxc_epoll_descr *);
|
||||||
|
|
||||||
callback cb[LXC_CMD_MAX] = {
|
callback cb[LXC_CMD_MAX] = {
|
||||||
[LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
|
[LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
|
||||||
[LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
|
[LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
|
||||||
[LXC_CMD_STOP] = lxc_cmd_stop_callback,
|
[LXC_CMD_STOP] = lxc_cmd_stop_callback,
|
||||||
[LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
|
[LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
|
||||||
[LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_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_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
|
||||||
[LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
|
[LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
|
||||||
[LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
|
[LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
|
||||||
[LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
|
[LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
|
||||||
[LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
|
[LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
|
||||||
[LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
|
[LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
|
||||||
[LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
|
[LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
|
||||||
[LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_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) {
|
if (req->cmd >= LXC_CMD_MAX) {
|
||||||
ERROR("Undefined command id %d", req->cmd);
|
ERROR("Undefined command id %d", req->cmd);
|
||||||
return -1;
|
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,
|
static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
|
||||||
struct lxc_epoll_descr *descr,
|
struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
|
||||||
const lxc_cmd_t cmd)
|
|
||||||
{
|
{
|
||||||
struct lxc_list *cur, *next;
|
struct lxc_list *cur, *next;
|
||||||
|
|
||||||
lxc_terminal_free(handler->conf, fd);
|
lxc_terminal_free(handler->conf, fd);
|
||||||
lxc_mainloop_del_handler(descr, 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) {
|
switch (cmd) {
|
||||||
struct lxc_state_client *client = cur->elem;
|
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)
|
if (client->clientfd != fd)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* kick client from list */
|
/* kick client from list */
|
||||||
lxc_list_del(cur);
|
lxc_list_del(cur);
|
||||||
close(client->clientfd);
|
close(client->clientfd);
|
||||||
free(cur->elem);
|
free(cur->elem);
|
||||||
free(cur);
|
free(cur);
|
||||||
/* No need to walk the whole list. If we found the state client
|
/* No need to walk the whole list. If we found the state
|
||||||
* fd there can't be a second one.
|
* client fd there can't be a second one.
|
||||||
*/
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1139,7 +1237,7 @@ static int lxc_cmd_handler(int fd, uint32_t events, void *data,
|
|||||||
req.data = reqdata;
|
req.data = reqdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = lxc_cmd_process(fd, &req, handler);
|
ret = lxc_cmd_process(fd, &req, handler, descr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* This is not an error, but only a request to close fd. */
|
/* This is not an error, but only a request to close fd. */
|
||||||
ret = LXC_MAINLOOP_CONTINUE;
|
ret = LXC_MAINLOOP_CONTINUE;
|
||||||
|
@ -46,6 +46,7 @@ typedef enum {
|
|||||||
LXC_CMD_ADD_STATE_CLIENT,
|
LXC_CMD_ADD_STATE_CLIENT,
|
||||||
LXC_CMD_CONSOLE_LOG,
|
LXC_CMD_CONSOLE_LOG,
|
||||||
LXC_CMD_SERVE_STATE_CLIENTS,
|
LXC_CMD_SERVE_STATE_CLIENTS,
|
||||||
|
LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
|
||||||
LXC_CMD_MAX,
|
LXC_CMD_MAX,
|
||||||
} lxc_cmd_t;
|
} lxc_cmd_t;
|
||||||
|
|
||||||
@ -124,5 +125,10 @@ extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
|
|||||||
extern int lxc_try_cmd(const char *name, const char *lxcpath);
|
extern int lxc_try_cmd(const char *name, const char *lxcpath);
|
||||||
extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
|
extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
|
||||||
struct lxc_console_log *log);
|
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 */
|
#endif /* __commands_h */
|
||||||
|
@ -2752,6 +2752,14 @@ struct lxc_conf *lxc_conf_init(void)
|
|||||||
new->lsm_aa_profile = NULL;
|
new->lsm_aa_profile = NULL;
|
||||||
lxc_list_init(&new->lsm_aa_raw);
|
lxc_list_init(&new->lsm_aa_raw);
|
||||||
new->lsm_se_context = NULL;
|
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 = false;
|
||||||
new->tmp_umount_proc = 0;
|
new->tmp_umount_proc = 0;
|
||||||
new->shmount.path_host = NULL;
|
new->shmount.path_host = NULL;
|
||||||
|
@ -299,6 +299,14 @@ struct lxc_conf {
|
|||||||
unsigned int seccomp_allow_nesting;
|
unsigned int seccomp_allow_nesting;
|
||||||
#if HAVE_SCMP_FILTER_CTX
|
#if HAVE_SCMP_FILTER_CTX
|
||||||
scmp_filter_ctx seccomp_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
|
#endif
|
||||||
int maincmd_fd;
|
int maincmd_fd;
|
||||||
unsigned int autodev; /* if 1, mount and fill a /dev at start */
|
unsigned int autodev; /* if 1, mount and fill a /dev at start */
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "af_unix.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "confile.h"
|
#include "confile.h"
|
||||||
@ -147,6 +148,7 @@ lxc_config_define(rootfs_options);
|
|||||||
lxc_config_define(rootfs_path);
|
lxc_config_define(rootfs_path);
|
||||||
lxc_config_define(seccomp_profile);
|
lxc_config_define(seccomp_profile);
|
||||||
lxc_config_define(seccomp_allow_nesting);
|
lxc_config_define(seccomp_allow_nesting);
|
||||||
|
lxc_config_define(seccomp_notify_proxy);
|
||||||
lxc_config_define(selinux_context);
|
lxc_config_define(selinux_context);
|
||||||
lxc_config_define(signal_halt);
|
lxc_config_define(signal_halt);
|
||||||
lxc_config_define(signal_reboot);
|
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.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.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.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.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.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, },
|
{ "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;
|
return -1;
|
||||||
|
|
||||||
if (lxc_conf->seccomp_allow_nesting > 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 -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#else
|
||||||
|
return minus_one_set_errno(ENOSYS);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_config_seccomp_profile(const char *key, const char *value,
|
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);
|
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,
|
static int get_config_seccomp_profile(const char *key, char *retv, int inlen,
|
||||||
struct lxc_conf *c, void *data)
|
struct lxc_conf *c, void *data)
|
||||||
{
|
{
|
||||||
@ -4294,6 +4332,18 @@ static inline int clr_config_seccomp_allow_nesting(const char *key,
|
|||||||
return 0;
|
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,
|
static inline int clr_config_seccomp_profile(const char *key,
|
||||||
struct lxc_conf *c, void *data)
|
struct lxc_conf *c, void *data)
|
||||||
{
|
{
|
||||||
|
@ -5227,6 +5227,28 @@ out:
|
|||||||
return ret;
|
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 *lxc_container_new(const char *name, const char *configpath)
|
||||||
{
|
{
|
||||||
struct lxc_container *c;
|
struct lxc_container *c;
|
||||||
@ -5351,6 +5373,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
|
|||||||
c->console_log = lxcapi_console_log;
|
c->console_log = lxcapi_console_log;
|
||||||
c->mount = lxcapi_mount;
|
c->mount = lxcapi_mount;
|
||||||
c->umount = lxcapi_umount;
|
c->umount = lxcapi_umount;
|
||||||
|
c->seccomp_notify = lxcapi_seccomp_notify;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
|
@ -31,6 +31,10 @@
|
|||||||
|
|
||||||
#include <lxc/attach_options.h>
|
#include <lxc/attach_options.h>
|
||||||
|
|
||||||
|
#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
|
||||||
|
#include <seccomp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -60,6 +64,21 @@ struct lxc_mount {
|
|||||||
int version;
|
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.
|
* An LXC container.
|
||||||
*
|
*
|
||||||
@ -867,6 +886,8 @@ struct lxc_container {
|
|||||||
*/
|
*/
|
||||||
int (*umount)(struct lxc_container *c, const char *target,
|
int (*umount)(struct lxc_container *c, const char *target,
|
||||||
unsigned long mountflags, struct lxc_mount *mnt);
|
unsigned long mountflags, struct lxc_mount *mnt);
|
||||||
|
|
||||||
|
int (*seccomp_notify)(struct lxc_container *c, unsigned int cmd, int fd);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -24,12 +24,20 @@
|
|||||||
#ifndef __LXC_LXCSECCOMP_H
|
#ifndef __LXC_LXCSECCOMP_H
|
||||||
#define __LXC_LXCSECCOMP_H
|
#define __LXC_LXCSECCOMP_H
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef HAVE_SECCOMP
|
||||||
|
#include <seccomp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#ifdef HAVE_SECCOMP
|
#ifdef HAVE_SECCOMP
|
||||||
extern int lxc_seccomp_load(struct lxc_conf *conf);
|
extern int lxc_seccomp_load(struct lxc_conf *conf);
|
||||||
extern int lxc_read_seccomp_config(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_conf *conf);
|
||||||
|
extern int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||||
|
struct lxc_epoll_descr *descr);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline int lxc_seccomp_load(struct lxc_conf *conf)
|
static inline int lxc_seccomp_load(struct lxc_conf *conf)
|
||||||
{
|
{
|
||||||
@ -46,6 +54,11 @@ static inline void lxc_seccomp_free(struct lxc_conf *conf)
|
|||||||
free(conf->seccomp);
|
free(conf->seccomp);
|
||||||
conf->seccomp = NULL;
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -407,4 +407,10 @@ enum {
|
|||||||
__internal_fd__; \
|
__internal_fd__; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define minus_one_set_errno(__errno__) \
|
||||||
|
({ \
|
||||||
|
errno = __errno__; \
|
||||||
|
-1; \
|
||||||
|
})
|
||||||
|
|
||||||
#endif /* __LXC_MACRO_H */
|
#endif /* __LXC_MACRO_H */
|
||||||
|
@ -31,9 +31,12 @@
|
|||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
#include "af_unix.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "lxccontainer.h"
|
||||||
#include "lxcseccomp.h"
|
#include "lxcseccomp.h"
|
||||||
|
#include "memory_utils.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#ifdef __MIPSEL__
|
#ifdef __MIPSEL__
|
||||||
@ -87,6 +90,10 @@ static const char *get_action_name(uint32_t action)
|
|||||||
return "trap";
|
return "trap";
|
||||||
case SCMP_ACT_ERRNO(0):
|
case SCMP_ACT_ERRNO(0):
|
||||||
return "errno";
|
return "errno";
|
||||||
|
#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
|
||||||
|
case SCMP_ACT_USER_NOTIF:
|
||||||
|
return "notify";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return "invalid action";
|
return "invalid action";
|
||||||
@ -116,6 +123,10 @@ static uint32_t get_v2_default_action(char *line)
|
|||||||
ret_action = SCMP_ACT_ALLOW;
|
ret_action = SCMP_ACT_ALLOW;
|
||||||
} else if (strncmp(line, "trap", 4) == 0) {
|
} else if (strncmp(line, "trap", 4) == 0) {
|
||||||
ret_action = SCMP_ACT_TRAP;
|
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]) {
|
} else if (line[0]) {
|
||||||
ERROR("Unrecognized seccomp action \"%s\"", line);
|
ERROR("Unrecognized seccomp action \"%s\"", line);
|
||||||
return -2;
|
return -2;
|
||||||
@ -928,6 +939,19 @@ static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_c
|
|||||||
goto bad_rule;
|
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,
|
if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line,
|
||||||
conf->seccomp_ctx, &rule))
|
conf->seccomp_ctx, &rule))
|
||||||
goto bad_rule;
|
goto bad_rule;
|
||||||
@ -1230,6 +1254,19 @@ int lxc_seccomp_load(struct lxc_conf *conf)
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1244,4 +1281,112 @@ void lxc_seccomp_free(struct lxc_conf *conf)
|
|||||||
conf->seccomp_ctx = NULL;
|
conf->seccomp_ctx = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
|
||||||
|
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);
|
||||||
|
|
||||||
|
notify_fd = lxc_unix_connect(&handler->conf->seccomp_notify_proxy_addr);
|
||||||
|
if (notify_fd < 0) {
|
||||||
|
SYSERROR("Failed to reconnect to seccomp proxy");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 30 second timeout */
|
||||||
|
if (lxc_socket_set_timeout(notify_fd, 30, 30)) {
|
||||||
|
SYSERROR("Failed to set socket timeout");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
handler->conf->seccomp_notify_proxy_fd = move_fd(notify_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_DECL_SECCOMP_NOTIF_GET_FD
|
||||||
|
static int seccomp_notify_default_answer(int fd, struct seccomp_notif *req,
|
||||||
|
struct seccomp_notif_resp *resp,
|
||||||
|
struct lxc_handler *handler)
|
||||||
|
{
|
||||||
|
resp->id = req->id;
|
||||||
|
resp->error = -ENOSYS;
|
||||||
|
|
||||||
|
if (seccomp_notif_send_resp(fd, resp))
|
||||||
|
SYSERROR("Failed to send default message to seccomp");
|
||||||
|
|
||||||
|
return seccomp_notify_reconnect(handler);
|
||||||
|
}
|
||||||
|
#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 reconnect_count, ret;
|
||||||
|
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_notify_proxy_msg msg;
|
||||||
|
|
||||||
|
if (listener_proxy_fd < 0) {
|
||||||
|
ERROR("No seccomp proxy registered");
|
||||||
|
return minus_one_set_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = seccomp_notif_receive(fd, req);
|
||||||
|
if (ret) {
|
||||||
|
SYSERROR("Failed to read seccomp notification");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&msg.req, req, sizeof(msg.req));
|
||||||
|
msg.monitor_pid = hdlr->monitor_pid;
|
||||||
|
msg.init_pid = hdlr->pid;
|
||||||
|
|
||||||
|
reconnect_count = 0;
|
||||||
|
do {
|
||||||
|
bytes = lxc_send_nointr(listener_proxy_fd, &msg, sizeof(msg),
|
||||||
|
MSG_NOSIGNAL);
|
||||||
|
if (bytes != (ssize_t)sizeof(msg)) {
|
||||||
|
SYSERROR("Failed to forward message to seccomp proxy");
|
||||||
|
if (seccomp_notify_default_answer(fd, req, resp, hdlr))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} while (reconnect_count++);
|
||||||
|
|
||||||
|
reconnect_count = 0;
|
||||||
|
do {
|
||||||
|
bytes = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);
|
||||||
|
if (bytes != (ssize_t)sizeof(msg)) {
|
||||||
|
SYSERROR("Failed to receive message from seccomp proxy");
|
||||||
|
if (seccomp_notify_default_answer(fd, req, resp, hdlr))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} while (reconnect_count++);
|
||||||
|
|
||||||
|
memcpy(resp, &msg.resp, sizeof(*resp));
|
||||||
|
ret = seccomp_notif_send_resp(fd, resp);
|
||||||
|
if (ret)
|
||||||
|
SYSERROR("Failed to send seccomp notification");
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -ENOSYS;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -591,6 +591,33 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
|
|||||||
goto out_mainloop_console;
|
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
|
||||||
|
|
||||||
if (has_console) {
|
if (has_console) {
|
||||||
struct lxc_terminal *console = &handler->conf->console;
|
struct lxc_terminal *console = &handler->conf->console;
|
||||||
|
|
||||||
@ -1094,6 +1121,9 @@ void lxc_abort(const char *name, struct lxc_handler *handler)
|
|||||||
|
|
||||||
static int do_start(void *data)
|
static int do_start(void *data)
|
||||||
{
|
{
|
||||||
|
struct lxc_handler *handler = data;
|
||||||
|
ATTR_UNUSED __do_close_prot_errno int data_sock0 = handler->data_sock[0],
|
||||||
|
data_sock1 = handler->data_sock[1];
|
||||||
int ret;
|
int ret;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
uid_t new_uid;
|
uid_t new_uid;
|
||||||
@ -1102,7 +1132,6 @@ static int do_start(void *data)
|
|||||||
uid_t nsuid = 0;
|
uid_t nsuid = 0;
|
||||||
gid_t nsgid = 0;
|
gid_t nsgid = 0;
|
||||||
int devnull_fd = -1;
|
int devnull_fd = -1;
|
||||||
struct lxc_handler *handler = data;
|
|
||||||
|
|
||||||
lxc_sync_fini_parent(handler);
|
lxc_sync_fini_parent(handler);
|
||||||
|
|
||||||
@ -1278,8 +1307,6 @@ static int do_start(void *data)
|
|||||||
|
|
||||||
/* Setup the container, ip, names, utsname, ... */
|
/* Setup the container, ip, names, utsname, ... */
|
||||||
ret = lxc_setup(handler);
|
ret = lxc_setup(handler);
|
||||||
close(handler->data_sock[1]);
|
|
||||||
close(handler->data_sock[0]);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ERROR("Failed to setup container \"%s\"", handler->name);
|
ERROR("Failed to setup container \"%s\"", handler->name);
|
||||||
goto out_warn_father;
|
goto out_warn_father;
|
||||||
@ -1330,6 +1357,20 @@ static int do_start(void *data)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_warn_father;
|
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);
|
ret = run_lxc_hooks(handler->name, "start", handler->conf, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ERROR("Failed to run lxc.hook.start for container \"%s\"",
|
ERROR("Failed to run lxc.hook.start for container \"%s\"",
|
||||||
@ -1592,6 +1633,7 @@ static inline int do_share_ns(void *arg)
|
|||||||
*/
|
*/
|
||||||
static int lxc_spawn(struct lxc_handler *handler)
|
static int lxc_spawn(struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
|
__do_close_prot_errno int data_sock0 = -EBADF, data_sock1 = -EBADF;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
char pidstr[20];
|
char pidstr[20];
|
||||||
bool wants_to_map_ids;
|
bool wants_to_map_ids;
|
||||||
@ -1624,6 +1666,8 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
handler->data_sock);
|
handler->data_sock);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_sync_fini;
|
goto out_sync_fini;
|
||||||
|
data_sock0 = handler->data_sock[0];
|
||||||
|
data_sock1 = handler->data_sock[1];
|
||||||
|
|
||||||
ret = resolve_clone_flags(handler);
|
ret = resolve_clone_flags(handler);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1888,6 +1932,26 @@ static int lxc_spawn(struct lxc_handler *handler)
|
|||||||
goto out_delete_net;
|
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);
|
ret = handler->ops->post_start(handler, handler->data);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_abort;
|
goto out_abort;
|
||||||
@ -1980,11 +2044,6 @@ int __lxc_start(const char *name, struct lxc_handler *handler,
|
|||||||
ERROR("Failed to spawn container \"%s\"", name);
|
ERROR("Failed to spawn container \"%s\"", name);
|
||||||
goto out_detach_blockdev;
|
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;
|
handler->conf->reboot = REBOOT_NONE;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user