[PATCH 4/7] um: skas: handle out-of-batch stub mmap notifications
Cong Wang <[email protected]> Fri, 19 Jun 2026 20:22:21 -0700
| Newsgroups | org.infradead.lists.linux-um |
|---|---|
| Message-ID | <599277ebecd4c7896c475553797d6969fd793efb.1781925126.git.xiyou.wangcong@gmail.com> |
From: Cong Wang <[email protected]> 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 <[email protected]> --- 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