From: Christian Brauner Date: Thu, 2 May 2019 15:06:00 +0000 (+0200) Subject: seccomp: send process memory fd X-Git-Tag: lxc-3.2.0~77^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2972%2Fhead;p=thirdparty%2Flxc.git seccomp: send process memory fd There's an inherent race when reading a process's memory. The easiest way is to have liblxc get an fd and check that the race was one, send it to the caller (They are free to ignore it if they don't use recvmsg()). Signed-off-by: Christian Brauner --- diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c index 7f0711ed2..9e2f8587c 100644 --- a/src/lxc/af_unix.c +++ b/src/lxc/af_unix.c @@ -199,6 +199,12 @@ again: return ret; } +int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, + size_t 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, void *data, size_t size) { diff --git a/src/lxc/af_unix.h b/src/lxc/af_unix.h index 3ae595498..8a068d920 100644 --- a/src/lxc/af_unix.h +++ b/src/lxc/af_unix.h @@ -35,6 +35,8 @@ extern void lxc_abstract_unix_close(int fd); extern int lxc_abstract_unix_connect(const char *path); extern int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, size_t size); +extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, + size_t size); extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds, void *data, size_t size); extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size); diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index f326c8d30..bfbc19ac5 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -1335,8 +1335,10 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, { #if HAVE_DECL_SECCOMP_NOTIF_GET_FD + __do_close_prot_errno int fd_mem = -EBADF; int reconnect_count, ret; ssize_t bytes; + char mem_path[6 + 21 + 5]; struct lxc_handler *hdlr = data; struct lxc_conf *conf = hdlr->conf; struct seccomp_notif *req = conf->seccomp.notifier.req_buf; @@ -1355,14 +1357,33 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, goto out; } + snprintf(mem_path, sizeof(mem_path), "/proc/%d/mem", req->pid); + fd_mem = open(mem_path, O_RDONLY | O_CLOEXEC); + if (fd_mem < 0) { + (void)seccomp_notify_default_answer(fd, req, resp, hdlr); + SYSERROR("Failed to open process memory for seccomp notify request"); + goto out; + } + + /* + * Make sure that the fd for /proc//mem we just opened still + * refers to the correct process's memory. + */ + ret = seccomp_notif_id_valid(fd, req->id); + if (ret < 0) { + (void)seccomp_notify_default_answer(fd, req, resp, hdlr); + SYSERROR("Invalid seccomp notify request id"); + 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); + bytes = lxc_unix_send_fds(listener_proxy_fd, &fd_mem, 1, &msg, + sizeof(msg)); if (bytes != (ssize_t)sizeof(msg)) { SYSERROR("Failed to forward message to seccomp proxy"); if (seccomp_notify_default_answer(fd, req, resp, hdlr)) @@ -1370,6 +1391,8 @@ int seccomp_notify_handler(int fd, uint32_t events, void *data, } } while (reconnect_count++); + close_prot_errno_disarm(fd_mem); + reconnect_count = 0; do { bytes = lxc_recv_nointr(listener_proxy_fd, &msg, sizeof(msg), 0);