[PATCH 4/7] um: skas: handle out-of-batch stub mmap notifications

Cong Wang xiyou.wangcong at gmail.com
Fri Jun 19 20:22:21 PDT 2026


From: Cong Wang <cwang at multikernel.io>

The mmap validation so far only runs for mmaps the monitor itself queued.
A hijacked stub can instead jump to the in-stub mmap on its own, outside
any batch. Such an mmap traps to the USER_NOTIF listener and suspends
in-kernel (so it discloses nothing) but it never signals the monitor
via the futex, so the monitor, waiting only on the futex, would block
forever (a guest-triggered DoS of the whole UML).

Drain the listener whenever the wait wakes: after each FUTEX_WAIT in
wait_stub_done_seccomp() (which already wakes periodically on SIGALRM and
tolerates EINTR), poll the listener non-blocking and service anything
pending. An out-of-batch mmap therefore stays suspended only until the
next wakeup and is then validated like any other: denied with -EPERM
unless it maps exactly what its PTE allows. No disclosure occurs while it
is pending, and the monitor no longer hangs.

Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Cong Wang <cwang at multikernel.io>
---
 arch/um/os-Linux/skas/process.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 3a31e52cdcf8..0987eb79ce76 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -32,6 +32,7 @@
 #include <linux/seccomp.h>
 #include <linux/threads.h>
 #include <sys/ioctl.h>
+#include <poll.h>
 #include <timetravel.h>
 #include <asm-generic/rwonce.h>
 #include "../internal.h"
@@ -215,6 +216,21 @@ static int seccomp_notify_serve(struct mm_id *mm_idp)
 	return 0;
 }
 
+static void seccomp_notify_drain(struct mm_id *mm_idp)
+{
+	struct pollfd pfd = {
+		.fd = mm_idp->seccomp_notify_fd,
+		.events = POLLIN,
+	};
+
+	if (mm_idp->seccomp_notify_fd < 0)
+		return;
+
+	while (poll(&pfd, 1, 0) > 0 && (pfd.revents & POLLIN))
+		if (seccomp_notify_serve(mm_idp) < 0)
+			break;
+}
+
 static void seccomp_serve_mmaps(struct mm_id *mm_idp)
 {
 	struct stub_data *data = (void *)mm_idp->stack;
@@ -265,6 +281,9 @@ void wait_stub_done_seccomp(struct mm_id *mm_idp, int running, int wait_sigsys)
 				       __func__, errno);
 				goto out_kill;
 			}
+
+			/* Handle any stub mmap that trapped out of band. */
+			seccomp_notify_drain(mm_idp);
 		} while (data->futex == FUTEX_IN_CHILD);
 
 		if (__READ_ONCE(mm_idp->pid) < 0)
-- 
2.43.0




More information about the linux-um mailing list