mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-27 11:13:50 +00:00
seccomp: update notify api
The previous API doesn't reflect the fact that `seccomp_notif` and `seccomp_notif_resp` are allocatd dynamically with sizes figured out at runtime. We now query the sizes via the seccomp(2) syscall and change `struct seccomp_notify_proxy_msg` to contain the sizes instead of the data, with the data following afterwards. Additionally it did not provide a convenient way to identify the container the message originated from, for which we now include a cookie configured via `lxc.seccomp.notify.cookie`. Since we currently always send exactly one request and await the response immediately, verify the `id` in the client's response. Finally, the proxy message's "version" field is removed, and we reserve 64 bits in its place. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
84cf6d259b
commit
4a094eec4a
@ -367,6 +367,7 @@ OLD_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $SECCOMP_CFLAGS"
|
||||
AC_CHECK_TYPES([scmp_filter_ctx], [], [], [[#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>]])
|
||||
CFLAGS="$OLD_CFLAGS"
|
||||
|
||||
|
@ -54,12 +54,21 @@ struct lxc_handler;
|
||||
|
||||
#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 {
|
||||
uint32_t version;
|
||||
struct seccomp_notif req;
|
||||
struct seccomp_notif_resp resp;
|
||||
uint64_t __reserved;
|
||||
pid_t monitor_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 {
|
||||
@ -67,6 +76,7 @@ struct seccomp_notify {
|
||||
int notify_fd;
|
||||
int proxy_fd;
|
||||
struct sockaddr_un proxy_addr;
|
||||
struct seccomp_notif_sizes sizes;
|
||||
struct seccomp_notif *req_buf;
|
||||
struct seccomp_notif_resp *rsp_buf;
|
||||
char *cookie;
|
||||
|
@ -49,8 +49,25 @@
|
||||
#define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_GET_NOTIF_SIZES
|
||||
#define SECCOMP_GET_NOTIF_SIZES 3
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -1333,6 +1350,8 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||
__do_close_prot_errno int fd_mem = -EBADF;
|
||||
int reconnect_count, ret;
|
||||
ssize_t bytes;
|
||||
struct iovec iov[4];
|
||||
size_t iov_len, msg_base_size, msg_full_size;
|
||||
char mem_path[6 /* /proc/ */
|
||||
+ INTTYPE_TO_STRLEN(int64_t)
|
||||
+ 3 /* mem */
|
||||
@ -1343,6 +1362,8 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||
struct seccomp_notif_resp *resp = conf->seccomp.notifier.rsp_buf;
|
||||
int listener_proxy_fd = conf->seccomp.notifier.proxy_fd;
|
||||
struct seccomp_notify_proxy_msg msg = {0};
|
||||
char *cookie = conf->seccomp.notifier.cookie;
|
||||
uint64_t req_id;
|
||||
|
||||
if (listener_proxy_fd < 0) {
|
||||
ERROR("No seccomp proxy registered");
|
||||
@ -1355,6 +1376,9 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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/mem", req->pid);
|
||||
fd_mem = open(mem_path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd_mem < 0) {
|
||||
@ -1374,15 +1398,38 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(&msg.req, req, sizeof(msg.req));
|
||||
msg.monitor_pid = hdlr->monitor_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;
|
||||
|
||||
iov[3].iov_base = cookie;
|
||||
msg_full_size += (iov[3].iov_len = len);
|
||||
|
||||
iov_len = 4;
|
||||
} else {
|
||||
iov_len = 3;
|
||||
}
|
||||
|
||||
reconnect_count = 0;
|
||||
do {
|
||||
bytes = lxc_unix_send_fds(listener_proxy_fd, &fd_mem, 1, &msg,
|
||||
sizeof(msg));
|
||||
if (bytes != (ssize_t)sizeof(msg)) {
|
||||
bytes = lxc_abstract_unix_send_fds_iov(listener_proxy_fd,
|
||||
&fd_mem, 1, iov,
|
||||
iov_len);
|
||||
if (bytes != (ssize_t)msg_full_size) {
|
||||
SYSERROR("Failed to forward message to seccomp proxy");
|
||||
if (seccomp_notify_default_answer(fd, req, resp, hdlr))
|
||||
goto out;
|
||||
@ -1391,17 +1438,24 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data,
|
||||
|
||||
close_prot_errno_disarm(fd_mem);
|
||||
|
||||
if (resp->id != req_id) {
|
||||
resp->id = req_id;
|
||||
ERROR("Proxy returned response with illegal id");
|
||||
(void)seccomp_notify_default_answer(fd, req, resp, hdlr);
|
||||
goto out;
|
||||
}
|
||||
|
||||
reconnect_count = 0;
|
||||
do {
|
||||
bytes = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);
|
||||
if (bytes != (ssize_t)sizeof(msg)) {
|
||||
bytes = lxc_recvmsg_nointr_iov(listener_proxy_fd, iov,iov_len,
|
||||
0);
|
||||
if (bytes != (ssize_t)msg_base_size) {
|
||||
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_notify_respond(fd, resp);
|
||||
if (ret)
|
||||
SYSERROR("Failed to send seccomp notification");
|
||||
@ -1454,6 +1508,13 @@ int lxc_seccomp_setup_proxy(struct lxc_seccomp *seccomp,
|
||||
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,
|
||||
&seccomp->notifier.rsp_buf);
|
||||
if (ret) {
|
||||
|
Loading…
Reference in New Issue
Block a user