Unthrottled kprintf log-flood DoS via umtx_sleep/wakeup on unmapped address
Summary
umtx_sleep(:150-156)/wakeup(:289-295) kprintf(WARNING cant translate) on unmapped in-range address with NO rate limit. Any unpriv user loops syscall(469,0x1000,...) -> one kernel msg per call. Floods msgbuf/dmesg/syslog. Serial console: synchronous blocking -> system-wide slowdown.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0202 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| umtx_flood.c | trigger-source | MAP_FIXED 2-page region, touch page 0, munmap page 1, hammer umtx_sleep on the hole | 3.0 KB | view raw |
| build.sh | build-script | cc -O2 -Wall | 189 B | view raw |
| run.sh | run-script | msgbuf before/after delta with WARNING flood proof | 634 B | view raw |
| VERDICT.md | verdict | full narrative | 2.6 KB | β raw |
| serial_flood_proof.txt | panic-signature | serial console backlog from a 2000-call flood that wedged the guest | 158.2 KB | view raw |
| fix.diff | suggested-fix | ratecheck() throttle on the umtx_sleep/umtx_wakeup WARNING kprintf | 1.8 KB | view raw |
| README.md | readme | human-facing summary | 1003 B | β raw |
| env.txt | environment | guest uname, modules, HW-gate note | 190 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0202 β umtx kprintf log-flood DoS
Summary
sys_umtx_sleep / sys_umtx_wakeup emit a kernel kprintf("WARNING
can't translate ...") on every call made on a leaf-PTE-invalid but
page-table-walk-resolvable user address, with no rate limit. Any
unprivileged user can flood the kernel msgbuf / dmesg / serial console.
Build / Run
./build.sh # cc -O2 -Wall -o umtx_flood umtx_flood.c
./run.sh 2000 # 2000 umtx_sleep calls; observe msgbuf delta
Expected (bug present)
- 2000 calls -> 2000
umtx_sleep() (A): WARNING can't translate ...lines added tokern.msgbuf. - Larger floods block the serial console (synchronous kprintf) and wedge the guest.
Expected (fixed kernel)
- 2000 calls -> exactly 1 msgbuf line (
ratecheck()1/s throttle).
Files
umtx_flood.cβ trigger PoC.fix.diffβ rate-limit viaratecheck().VERDICT.mdβ full narrative + reproduction transcript.serial_flood_proof.txtβ guest-wedging serial backlog.
DF-0202 β Unthrottled kprintf log-flood DoS via umtx
Verdict: REPRODUCED (DoS). Fix VALIDATED.
Mechanism
sys_umtx_sleep (sys/kern/kern_umtx.c:150-156) and sys_umtx_wakeup
(:289-295) emit one kprintf("... WARNING can't translate ...") for
every call made on a user address whose leaf PTE is invalid but whose
page-table-walk is otherwise resolvable (e.g. an address inside a hole
punched out of a populated mmap region). There is NO rate limit.
Any unprivileged user can loop syscall(SYS_umtx_sleep, target, ...) and
emit one kernel message per call. At ~300 calls/second the kernel msgbuf
fills with attacker-controlled lines, dmesg becomes useless, and on a
system with the serial console active (the audit guest) the synchronous
blocking writes wedge the entire machine β observed directly during
verification (the guest stopped answering ssh after a 2000-call burst;
boot.log shows the serial backlog).
Trigger
The hole-punched-mmap approach is needed because for a totally
unmapped address (e.g. 0x1000), kreadmem64(PTmap+...) itself faults
reading the (absent) page-table page, returns -1, and -1 happens to
have the PG_V bit set β so uservtophys() returns a garbage "valid"
physical address and the WARNING guard waddr == -1 is never taken
(the call instead returns EBUSY via the value-mismatch path). When
the target VA shares a populated 2 MiB page-table page with an
adjacent mapped page (so the PTmap walk succeeds but the leaf PTE is
invalid), uservtophys() returns -1 correctly and the WARNING path
fires.
umtx_flood.c therefore does MAP_FIXED at an isolated region
(0x50000000), touches page 0 (populates the PDE), munmaps page 1
(leaves its PTE invalid while the PDE remains present), then hammers
umtx_sleep(page_1, 0xffffffff, 1). Each call emits one WARNING.
Reproduction
$ ./build.sh && ./run.sh 2000 before_umtx_lines=0 DF-0202: 2000 umtx_sleep calls in 7.002s (286 calls/s) DF-0202: returns: EINVAL=2000 other=0 after_umtx_lines=2000 delta=2000 umtx_sleep() (A): WARNING can't translate 0x50001000 (umtx_flood 1369/1)
Each call = one msgbuf line. 2000 calls produce 2000 lines. During
verification a larger flood blocked the serial console and the guest
became unresponsive β see serial_flood_proof.txt.
Fix (validated)
fix.diff wraps both kprintf sites with ratecheck() limited to 1
message/second. On the patched kernel (#1, sha256
a4b8ef09f60586a8e1615aad22242264ada3c78bb2c6ea8edf7caec8798d96c7) the
same 2000-call PoC emits exactly 1 msgbuf line:
DF-0202: 2000 umtx_sleep calls in 0.008s (256238 calls/s) DF-0202: returns: EINVAL=2000 other=0 after_umtx_lines=1 delta=1
Fix verification
fixedvalidated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (live). umtx_sleep/wakeup unthrottled kprintf -> 2000 msgbuf lines + serial console wedge. Unprivileged.
No comments yet.