[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