[lxc-devel] [lxc/master] seccomp: send process memory fd

brauner on Github lxc-bot at linuxcontainers.org
Thu May 2 15:17:38 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 584 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190502/b87ad45f/attachment.bin>
-------------- next part --------------
From 5ed06d3ad6a80a7a8efd10a9c01e90e0e7981306 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 2 May 2019 17:06:00 +0200
Subject: [PATCH] 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 <christian.brauner at ubuntu.com>
---
 src/lxc/af_unix.c |  6 ++++++
 src/lxc/af_unix.h |  2 ++
 src/lxc/seccomp.c | 27 +++++++++++++++++++++++++--
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/src/lxc/af_unix.c b/src/lxc/af_unix.c
index 7f0711ed22..9e2f8587c8 100644
--- a/src/lxc/af_unix.c
+++ b/src/lxc/af_unix.c
@@ -199,6 +199,12 @@ int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
 	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 3ae5954983..8a068d920f 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 f326c8d307..bfbc19ac53 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/<pid>/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);


More information about the lxc-devel mailing list