Unverified Commit 26077e91 by Christian Brauner Committed by GitHub

Merge pull request #3080 from Blub/seccomp-notify-api

Seccomp notify api update
parents cfc3b342 b9dab9ef
...@@ -367,6 +367,7 @@ OLD_CFLAGS="$CFLAGS" ...@@ -367,6 +367,7 @@ 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_notify_fd], [], [], [[#include <seccomp.h>]]) AC_CHECK_DECLS([seccomp_notify_fd], [], [], [[#include <seccomp.h>]])
AC_CHECK_TYPES([struct seccomp_notif_sizes], [], [], [[#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"
......
...@@ -1997,11 +1997,22 @@ dev/null proc/kcore none bind,relative 0 0 ...@@ -1997,11 +1997,22 @@ dev/null proc/kcore none bind,relative 0 0
<listitem> <listitem>
<para> <para>
Specify a unix socket to which LXC will connect and forward Specify a unix socket to which LXC will connect and forward
seccomp events to. The path must by in the form seccomp events to. The path must be in the form
unix:/path/to/socket or unix:@socket. The former specifies a unix:/path/to/socket or unix:@socket. The former specifies a
path-bound unix domain socket while the latter specifies an path-bound unix domain socket while the latter specifies an
abstract unix domain socket. abstract unix domain socket.
</para> </para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>lxc.seccomp.notify.cookie</option>
</term>
<listitem>
<para>
An additional string sent along with proxied seccomp notification
requests.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
......
...@@ -153,19 +153,16 @@ int lxc_abstract_unix_connect(const char *path) ...@@ -153,19 +153,16 @@ int lxc_abstract_unix_connect(const char *path)
return fd; return fd;
} }
int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, int lxc_abstract_unix_send_fds_iov(int fd, int *sendfds, int num_sendfds,
void *data, size_t size) struct iovec *iov, size_t iovlen)
{ {
__do_free char *cmsgbuf = NULL; __do_free char *cmsgbuf = NULL;
int ret; int ret;
struct msghdr msg; struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg = NULL; struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int)); size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int));
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
cmsgbuf = malloc(cmsgbufsize); cmsgbuf = malloc(cmsgbufsize);
if (!cmsgbuf) { if (!cmsgbuf) {
...@@ -185,10 +182,8 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, ...@@ -185,10 +182,8 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int)); memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int));
iov.iov_base = data ? data : buf; msg.msg_iov = iov;
iov.iov_len = data ? size : sizeof(buf); msg.msg_iovlen = iovlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
again: again:
ret = sendmsg(fd, &msg, MSG_NOSIGNAL); ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
...@@ -199,26 +194,35 @@ again: ...@@ -199,26 +194,35 @@ again:
return ret; return ret;
} }
int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
void *data, size_t size)
{
char buf[1] = {0};
struct iovec iov = {
.iov_base = data ? data : buf,
.iov_len = data ? size : sizeof(buf),
};
return lxc_abstract_unix_send_fds_iov(fd, sendfds, num_sendfds, &iov,
1);
}
int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data,
size_t size) size_t size)
{ {
return lxc_abstract_unix_send_fds(fd, sendfds, num_sendfds, data, size); return lxc_abstract_unix_send_fds(fd, sendfds, num_sendfds, data, size);
} }
int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, static int lxc_abstract_unix_recv_fds_iov(int fd, int *recvfds, int num_recvfds,
void *data, size_t size) struct iovec *iov, size_t iovlen)
{ {
__do_free char *cmsgbuf = NULL; __do_free char *cmsgbuf = NULL;
int ret; int ret;
struct msghdr msg; struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg = NULL; struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) + size_t cmsgbufsize = CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(num_recvfds * sizeof(int)); CMSG_SPACE(num_recvfds * sizeof(int));
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
cmsgbuf = malloc(cmsgbufsize); cmsgbuf = malloc(cmsgbufsize);
if (!cmsgbuf) { if (!cmsgbuf) {
...@@ -229,10 +233,8 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, ...@@ -229,10 +233,8 @@ int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
msg.msg_control = cmsgbuf; msg.msg_control = cmsgbuf;
msg.msg_controllen = cmsgbufsize; msg.msg_controllen = cmsgbufsize;
iov.iov_base = data ? data : buf; msg.msg_iov = iov;
iov.iov_len = data ? size : sizeof(buf); msg.msg_iovlen = iovlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
again: again:
ret = recvmsg(fd, &msg, 0); ret = recvmsg(fd, &msg, 0);
...@@ -264,6 +266,17 @@ out: ...@@ -264,6 +266,17 @@ out:
return ret; return ret;
} }
int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
void *data, size_t size)
{
char buf[1] = {0};
struct iovec iov = {
.iov_base = data ? data : buf,
.iov_len = data ? size : sizeof(buf),
};
return lxc_abstract_unix_recv_fds_iov(fd, recvfds, num_recvfds, &iov, 1);
}
int lxc_abstract_unix_send_credential(int fd, void *data, size_t size) int lxc_abstract_unix_send_credential(int fd, void *data, size_t size)
{ {
struct msghdr msg = {0}; struct msghdr msg = {0};
...@@ -365,13 +378,13 @@ int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path) ...@@ -365,13 +378,13 @@ int lxc_unix_sockaddr(struct sockaddr_un *ret, const char *path)
return (int)(offsetof(struct sockaddr_un, sun_path) + len + 1); return (int)(offsetof(struct sockaddr_un, sun_path) + len + 1);
} }
int lxc_unix_connect(struct sockaddr_un *addr) int lxc_unix_connect_type(struct sockaddr_un *addr, int type)
{ {
__do_close_prot_errno int fd = -EBADF; __do_close_prot_errno int fd = -EBADF;
int ret; int ret;
ssize_t len; ssize_t len;
fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); fd = socket(AF_UNIX, type | SOCK_CLOEXEC, 0);
if (fd < 0) { if (fd < 0) {
SYSERROR("Failed to open new AF_UNIX socket"); SYSERROR("Failed to open new AF_UNIX socket");
return -1; return -1;
...@@ -392,6 +405,11 @@ int lxc_unix_connect(struct sockaddr_un *addr) ...@@ -392,6 +405,11 @@ int lxc_unix_connect(struct sockaddr_un *addr)
return move_fd(fd); return move_fd(fd);
} }
int lxc_unix_connect(struct sockaddr_un *addr, int type)
{
return lxc_unix_connect_type(addr, SOCK_STREAM);
}
int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout) int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout)
{ {
struct timeval out = {0}; struct timeval out = {0};
......
...@@ -35,6 +35,9 @@ extern void lxc_abstract_unix_close(int fd); ...@@ -35,6 +35,9 @@ extern void lxc_abstract_unix_close(int fd);
extern int lxc_abstract_unix_connect(const char *path); extern int lxc_abstract_unix_connect(const char *path);
extern int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, extern int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
void *data, size_t size); void *data, size_t size);
extern int lxc_abstract_unix_send_fds_iov(int fd, int *sendfds,
int num_sendfds, struct iovec *iov,
size_t iovlen);
extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data,
size_t size); size_t size);
extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
...@@ -43,6 +46,7 @@ extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size); ...@@ -43,6 +46,7 @@ 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_sockaddr(struct sockaddr_un *ret, const char *path);
extern int lxc_unix_connect(struct sockaddr_un *addr); extern int lxc_unix_connect(struct sockaddr_un *addr);
extern int lxc_unix_connect_type(struct sockaddr_un *addr, int type);
extern int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout); extern int lxc_socket_set_timeout(int fd, int rcv_timeout, int snd_timeout);
#endif /* __LXC_AF_UNIX_H */ #endif /* __LXC_AF_UNIX_H */
...@@ -153,6 +153,7 @@ lxc_config_define(rootfs_options); ...@@ -153,6 +153,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_cookie);
lxc_config_define(seccomp_notify_proxy); 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);
...@@ -246,6 +247,7 @@ static struct lxc_config_t config_jump_table[] = { ...@@ -246,6 +247,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.cookie", set_config_seccomp_notify_cookie, get_config_seccomp_notify_cookie, clr_config_seccomp_notify_cookie, },
{ "lxc.seccomp.notify.proxy", set_config_seccomp_notify_proxy, get_config_seccomp_notify_proxy, clr_config_seccomp_notify_proxy, }, { "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, },
...@@ -1013,6 +1015,16 @@ static int set_config_seccomp_allow_nesting(const char *key, const char *value, ...@@ -1013,6 +1015,16 @@ static int set_config_seccomp_allow_nesting(const char *key, const char *value,
#endif #endif
} }
static int set_config_seccomp_notify_cookie(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
#ifdef HAVE_SECCOMP_NOTIFY
return set_config_string_item(&lxc_conf->seccomp.notifier.cookie, value);
#else
return minus_one_set_errno(ENOSYS);
#endif
}
static int set_config_seccomp_notify_proxy(const char *key, const char *value, static int set_config_seccomp_notify_proxy(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data) struct lxc_conf *lxc_conf, void *data)
{ {
...@@ -3955,6 +3967,16 @@ static int get_config_seccomp_allow_nesting(const char *key, char *retv, ...@@ -3955,6 +3967,16 @@ static int get_config_seccomp_allow_nesting(const char *key, char *retv,
#endif #endif
} }
static int get_config_seccomp_notify_cookie(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
#ifdef HAVE_SECCOMP_NOTIFY
return lxc_get_conf_str(retv, inlen, c->seccomp.notifier.cookie);
#else
return minus_one_set_errno(ENOSYS);
#endif
}
static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inlen, static int get_config_seccomp_notify_proxy(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
...@@ -4563,6 +4585,18 @@ static inline int clr_config_seccomp_allow_nesting(const char *key, ...@@ -4563,6 +4585,18 @@ static inline int clr_config_seccomp_allow_nesting(const char *key,
#endif #endif
} }
static inline int clr_config_seccomp_notify_cookie(const char *key,
struct lxc_conf *c, void *data)
{
#ifdef HAVE_SECCOMP_NOTIFY
free(c->seccomp.notifier.cookie);
c->seccomp.notifier.cookie = NULL;
return 0;
#else
return minus_one_set_errno(ENOSYS);
#endif
}
static inline int clr_config_seccomp_notify_proxy(const char *key, static inline int clr_config_seccomp_notify_proxy(const char *key,
struct lxc_conf *c, void *data) struct lxc_conf *c, void *data)
{ {
......
...@@ -142,6 +142,24 @@ again: ...@@ -142,6 +142,24 @@ again:
return ret; return ret;
} }
ssize_t lxc_recvmsg_nointr_iov(int sockfd, struct iovec *iov, size_t iovlen,
int flags)
{
ssize_t ret;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = iovlen;
again:
ret = recvmsg(sockfd, &msg, flags);
if (ret < 0 && errno == EINTR)
goto again;
return ret;
}
ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, const void *expected_buf) ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, const void *expected_buf)
{ {
ssize_t ret; ssize_t ret;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/uio.h>
#include <sys/vfs.h> #include <sys/vfs.h>
#include <unistd.h> #include <unistd.h>
...@@ -43,6 +44,8 @@ extern ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count, ...@@ -43,6 +44,8 @@ extern ssize_t lxc_read_nointr_expect(int fd, void *buf, size_t count,
extern ssize_t lxc_read_file_expect(const char *path, void *buf, size_t count, extern ssize_t lxc_read_file_expect(const char *path, void *buf, size_t count,
const void *expected_buf); const void *expected_buf);
extern ssize_t lxc_recv_nointr(int sockfd, void *buf, size_t len, int flags); extern ssize_t lxc_recv_nointr(int sockfd, void *buf, size_t len, int flags);
ssize_t lxc_recvmsg_nointr_iov(int sockfd, struct iovec *iov, size_t iovlen,
int flags);
extern bool file_exists(const char *f); extern bool file_exists(const char *f);
extern int print_to_file(const char *file, const char *content); extern int print_to_file(const char *file, const char *content);
......
...@@ -54,12 +54,21 @@ struct lxc_handler; ...@@ -54,12 +54,21 @@ struct lxc_handler;
#if HAVE_DECL_SECCOMP_NOTIFY_FD #if HAVE_DECL_SECCOMP_NOTIFY_FD
#if !HAVE_STRUCT_SECCOMP_NOTIF_SIZES
struct seccomp_notif_sizes {
__u16 seccomp_notif;
__u16 seccomp_notif_resp;
__u16 seccomp_data;
};
#endif
struct seccomp_notify_proxy_msg { struct seccomp_notify_proxy_msg {
uint32_t version; uint64_t __reserved;
struct seccomp_notif req;
struct seccomp_notif_resp resp;
pid_t monitor_pid; pid_t monitor_pid;
pid_t init_pid; pid_t init_pid;
struct seccomp_notif_sizes sizes;
uint64_t cookie_len;
/* followed by: seccomp_notif, seccomp_notif_resp, cookie */
}; };
struct seccomp_notify { struct seccomp_notify {
...@@ -67,8 +76,10 @@ struct seccomp_notify { ...@@ -67,8 +76,10 @@ struct seccomp_notify {
int notify_fd; int notify_fd;
int proxy_fd; int proxy_fd;
struct sockaddr_un proxy_addr; struct sockaddr_un proxy_addr;
struct seccomp_notif_sizes sizes;
struct seccomp_notif *req_buf; struct seccomp_notif *req_buf;
struct seccomp_notif_resp *rsp_buf; struct seccomp_notif_resp *rsp_buf;
char *cookie;
}; };
#define HAVE_SECCOMP_NOTIFY 1 #define HAVE_SECCOMP_NOTIFY 1
......
...@@ -49,8 +49,25 @@ ...@@ -49,8 +49,25 @@
#define MIPS_ARCH_N64 lxc_seccomp_arch_mips64 #define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
#endif #endif
#ifndef SECCOMP_GET_NOTIF_SIZES
#define SECCOMP_GET_NOTIF_SIZES 3
#endif
lxc_log_define(seccomp, lxc); lxc_log_define(seccomp, lxc);
#if HAVE_DECL_SECCOMP_NOTIFY_FD
static inline int __seccomp(unsigned int operation, unsigned int flags,
void *args)
{
#ifdef __NR_seccomp
return syscall(__NR_seccomp, operation, flags, args);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
static int parse_config_v1(FILE *f, char *line, size_t *line_bufsz, struct lxc_conf *conf) static int parse_config_v1(FILE *f, char *line, size_t *line_bufsz, struct lxc_conf *conf)
{ {
int ret = 0; int ret = 0;
...@@ -1294,7 +1311,8 @@ static int seccomp_notify_reconnect(struct lxc_handler *handler) ...@@ -1294,7 +1311,8 @@ static int seccomp_notify_reconnect(struct lxc_handler *handler)
close_prot_errno_disarm(handler->conf->seccomp.notifier.proxy_fd); close_prot_errno_disarm(handler->conf->seccomp.notifier.proxy_fd);
notify_fd = lxc_unix_connect(&handler->conf->seccomp.notifier.proxy_addr); notify_fd = lxc_unix_connect_type(
&handler->conf->seccomp.notifier.proxy_addr, SOCK_SEQPACKET);
if (notify_fd < 0) { if (notify_fd < 0) {
SYSERROR("Failed to reconnect to seccomp proxy"); SYSERROR("Failed to reconnect to seccomp proxy");
return -1; return -1;
...@@ -1311,17 +1329,15 @@ static int seccomp_notify_reconnect(struct lxc_handler *handler) ...@@ -1311,17 +1329,15 @@ static int seccomp_notify_reconnect(struct lxc_handler *handler)
#endif #endif
#if HAVE_DECL_SECCOMP_NOTIFY_FD #if HAVE_DECL_SECCOMP_NOTIFY_FD
static int seccomp_notify_default_answer(int fd, struct seccomp_notif *req, static void seccomp_notify_default_answer(int fd, struct seccomp_notif *req,
struct seccomp_notif_resp *resp, struct seccomp_notif_resp *resp,
struct lxc_handler *handler) struct lxc_handler *handler)
{ {
resp->id = req->id; resp->id = req->id;
resp->error = -ENOSYS; resp->error = -ENOSYS;
if (seccomp_notify_respond(fd, resp)) if (seccomp_notify_respond(fd, resp))
SYSERROR("Failed to send default message to seccomp"); SYSERROR("Failed to send default message to seccomp");
return seccomp_notify_reconnect(handler);
} }
#endif #endif
...@@ -1330,24 +1346,26 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, ...@@ -1330,24 +1346,26 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
{ {
#if HAVE_DECL_SECCOMP_NOTIFY_FD #if HAVE_DECL_SECCOMP_NOTIFY_FD
__do_close_prot_errno int fd_pid = -EBADF;
__do_close_prot_errno int fd_mem = -EBADF; __do_close_prot_errno int fd_mem = -EBADF;
int reconnect_count, ret; int ret;
ssize_t bytes; ssize_t bytes;
int send_fd_list[2];
struct iovec iov[4];
size_t iov_len, msg_base_size, msg_full_size;
char mem_path[6 /* /proc/ */ char mem_path[6 /* /proc/ */
+ INTTYPE_TO_STRLEN(int64_t) + INTTYPE_TO_STRLEN(int64_t)
+ 3 /* mem */ + 3 /* mem */
+ 1 /* \0 */]; + 1 /* \0 */];
bool reconnected = false;
struct lxc_handler *hdlr = data; struct lxc_handler *hdlr = data;
struct lxc_conf *conf = hdlr->conf; struct lxc_conf *conf = hdlr->conf;
struct seccomp_notif *req = conf->seccomp.notifier.req_buf; struct seccomp_notif *req = conf->seccomp.notifier.req_buf;
struct seccomp_notif_resp *resp = conf->seccomp.notifier.rsp_buf; struct seccomp_notif_resp *resp = conf->seccomp.notifier.rsp_buf;
int listener_proxy_fd = conf->seccomp.notifier.proxy_fd; int listener_proxy_fd = conf->seccomp.notifier.proxy_fd;
struct seccomp_notify_proxy_msg msg = {0}; struct seccomp_notify_proxy_msg msg = {0};
char *cookie = conf->seccomp.notifier.cookie;
if (listener_proxy_fd < 0) { uint64_t req_id;
ERROR("No seccomp proxy registered");
return minus_one_set_errno(EINVAL);
}
ret = seccomp_notify_receive(fd, req); ret = seccomp_notify_receive(fd, req);
if (ret) { if (ret) {
...@@ -1355,10 +1373,36 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, ...@@ -1355,10 +1373,36 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
goto out; goto out;
} }
if (listener_proxy_fd < 0) {
ret = -1;
/* Same condition as for the initial setup_proxy() */
if (conf->seccomp.notifier.wants_supervision &&
conf->seccomp.notifier.proxy_addr.sun_path[1] != '\0') {
ret = seccomp_notify_reconnect(hdlr);
}
if (ret) {
ERROR("No seccomp proxy registered");
seccomp_notify_default_answer(fd, req, resp, hdlr);
goto out;
}
listener_proxy_fd = conf->seccomp.notifier.proxy_fd;
}
/* remember the ID in case we receive garbage from the proxy */
resp->id = req_id = req->id;
snprintf(mem_path, sizeof(mem_path), "/proc/%d", req->pid);
fd_pid = open(mem_path, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (fd_pid < 0) {
seccomp_notify_default_answer(fd, req, resp, hdlr);
SYSERROR("Failed to open process pidfd for seccomp notify request");
goto out;
}
snprintf(mem_path, sizeof(mem_path), "/proc/%d/mem", req->pid); snprintf(mem_path, sizeof(mem_path), "/proc/%d/mem", req->pid);
fd_mem = open(mem_path, O_RDONLY | O_CLOEXEC); fd_mem = open(mem_path, O_RDONLY | O_CLOEXEC);
if (fd_mem < 0) { if (fd_mem < 0) {
(void)seccomp_notify_default_answer(fd, req, resp, hdlr); seccomp_notify_default_answer(fd, req, resp, hdlr);
SYSERROR("Failed to open process memory for seccomp notify request"); SYSERROR("Failed to open process memory for seccomp notify request");
goto out; goto out;
} }
...@@ -1369,39 +1413,80 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, ...@@ -1369,39 +1413,80 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
*/ */
ret = seccomp_notify_id_valid(fd, req->id); ret = seccomp_notify_id_valid(fd, req->id);
if (ret < 0) { if (ret < 0) {
(void)seccomp_notify_default_answer(fd, req, resp, hdlr); seccomp_notify_default_answer(fd, req, resp, hdlr);
SYSERROR("Invalid seccomp notify request id"); SYSERROR("Invalid seccomp notify request id");
goto out; goto out;
} }
memcpy(&msg.req, req, sizeof(msg.req));
msg.monitor_pid = hdlr->monitor_pid; msg.monitor_pid = hdlr->monitor_pid;
msg.init_pid = hdlr->pid; msg.init_pid = hdlr->pid;
memcpy(&msg.sizes, &conf->seccomp.notifier.sizes, sizeof(msg.sizes));
msg_base_size = 0;
iov[0].iov_base = &msg;
msg_base_size += (iov[0].iov_len = sizeof(msg));
iov[1].iov_base = req;
msg_base_size += (iov[1].iov_len = msg.sizes.seccomp_notif);
iov[2].iov_base = resp;
msg_base_size += (iov[2].iov_len = msg.sizes.seccomp_notif_resp);
msg_full_size = msg_base_size;
if (cookie) {
size_t len = strlen(cookie);
msg.cookie_len = (uint64_t)len;
reconnect_count = 0; iov[3].iov_base = cookie;
do { msg_full_size += (iov[3].iov_len = len);
bytes = lxc_unix_send_fds(listener_proxy_fd, &fd_mem, 1, &msg,
sizeof(msg)); iov_len = 4;
if (bytes != (ssize_t)sizeof(msg)) { } else {
SYSERROR("Failed to forward message to seccomp proxy"); iov_len = 3;
if (seccomp_notify_default_answer(fd, req, resp, hdlr)) }
goto out;
send_fd_list[0] = fd_pid;
send_fd_list[1] = fd_mem;
retry:
bytes = lxc_abstract_unix_send_fds_iov(listener_proxy_fd, send_fd_list,
2, iov, iov_len);
if (bytes != (ssize_t)msg_full_size) {
SYSERROR("Failed to forward message to seccomp proxy");
if (!reconnected) {
ret = seccomp_notify_reconnect(hdlr);
if (ret == 0) {
reconnected = true;
goto retry;
}
} }
} while (reconnect_count++);
seccomp_notify_default_answer(fd, req, resp, hdlr);
goto out;
}
close_prot_errno_disarm(fd_mem); close_prot_errno_disarm(fd_mem);
reconnect_count = 0; if (msg.__reserved != 0) {
do { ERROR("Proxy filled reserved data in response");
bytes = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0); seccomp_notify_default_answer(fd, req, resp, hdlr);
if (bytes != (ssize_t)sizeof(msg)) { goto out;
SYSERROR("Failed to receive message from seccomp proxy"); }
if (seccomp_notify_default_answer(fd, req, resp, hdlr))
goto out; if (resp->id != req_id) {
} resp->id = req_id;
} while (reconnect_count++); ERROR("Proxy returned response with illegal id");
seccomp_notify_default_answer(fd, req, resp, hdlr);
goto out;
}
bytes = lxc_recvmsg_nointr_iov(listener_proxy_fd, iov,iov_len,
MSG_TRUNC);
if (bytes != (ssize_t)msg_base_size) {
SYSERROR("Failed to receive message from seccomp proxy");
seccomp_notify_default_answer(fd, req, resp, hdlr);
goto out;
}
memcpy(resp, &msg.resp, sizeof(*resp));
ret = seccomp_notify_respond(fd, resp); ret = seccomp_notify_respond(fd, resp);
if (ret) if (ret)
SYSERROR("Failed to send seccomp notification"); SYSERROR("Failed to send seccomp notification");
...@@ -1441,7 +1526,8 @@ int lxc_seccomp_setup_proxy(struct lxc_seccomp *seccomp, ...@@ -1441,7 +1526,8 @@ int lxc_seccomp_setup_proxy(struct lxc_seccomp *seccomp,
__do_close_prot_errno int notify_fd = -EBADF; __do_close_prot_errno int notify_fd = -EBADF;
int ret; int ret;
notify_fd = lxc_unix_connect(&seccomp->notifier.proxy_addr); notify_fd = lxc_unix_connect_type(&seccomp->notifier.proxy_addr,
SOCK_SEQPACKET);
if (notify_fd < 0) { if (notify_fd < 0) {
SYSERROR("Failed to connect to seccomp proxy"); SYSERROR("Failed to connect to seccomp proxy");
return -1; return -1;
...@@ -1454,6 +1540,13 @@ int lxc_seccomp_setup_proxy(struct lxc_seccomp *seccomp, ...@@ -1454,6 +1540,13 @@ int lxc_seccomp_setup_proxy(struct lxc_seccomp *seccomp,
return -1; return -1;
} }
ret = __seccomp(SECCOMP_GET_NOTIF_SIZES, 0,
&seccomp->notifier.sizes);
if (ret) {
SYSERROR("Failed to query seccomp notify struct sizes");
return -1;
}
ret = seccomp_notify_alloc(&seccomp->notifier.req_buf, ret = seccomp_notify_alloc(&seccomp->notifier.req_buf,
&seccomp->notifier.rsp_buf); &seccomp->notifier.rsp_buf);
if (ret) { if (ret) {
......
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