kern/60377: x86 cpu_uarea_alloc: pmap_update before freeing redzone pages

"[email protected] via gnats" <[email protected]>
Newsgroups gmane.os.netbsd.bugs
Message-ID <[email protected]>
>Number:         60377
>Category:       kern
>Synopsis:       x86 cpu_uarea_alloc: pmap_update before freeing redzone pages
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jun 28 06:55:00 +0000 2026
>Originator:     Kevin Bowling
>Release:        trunk
>Organization:
NetBSD
>Environment:
>Description:
The two pmap_kremove calls had a single trailing pmap_update, leaving
the freed redzone pages reachable through stale TLB entries on remote
CPUs between the uvm_pagefree calls and the eventual shootdown.

Batch both kremoves, then pmap_update, then both frees.

>How-To-Repeat:

>Fix:
diff --git a/sys/arch/x86/x86/vm_machdep.c b/sys/arch/x86/x86/vm_machdep.c
index 7d70835f1b6e..800210175e39 100644
--- a/sys/arch/x86/x86/vm_machdep.c
+++ b/sys/arch/x86/x86/vm_machdep.c
@@ -364,8 +364,8 @@ vunmapbuf(struct buf *bp, vsize_t len)
 void *
 cpu_uarea_alloc(bool system)
 {
-       vaddr_t base, va;
-       paddr_t pa;
+       vaddr_t base, va, va_lo, va_hi;
+       paddr_t pa_lo, pa_hi;
        struct pcb *pcb;
 
        base = uvm_km_alloc(kernel_map, USPACE + PAGE_SIZE, 0,
@@ -402,23 +402,19 @@ cpu_uarea_alloc(bool system)
                pcb->pcb_savefpu = &pcb->pcb_savefpusmall;
        }
 
-       /* Page[1] = RedZone */
-       va = base + PAGE_SIZE;
-       if (!pmap_extract(pmap_kernel(), va, &pa)) {
+       va_lo = base + PAGE_SIZE;
+       va_hi = base + USPACE;
+       if (!pmap_extract(pmap_kernel(), va_lo, &pa_lo)) {
                panic("%s: impossible, Page[1] unmapped", __func__);
        }
-       pmap_kremove(va, PAGE_SIZE);
-       uvm_pagefree(PHYS_TO_VM_PAGE(pa));
-
-       /* Page[UPAGES] = RedZone */
-       va = base + USPACE;
-       if (!pmap_extract(pmap_kernel(), va, &pa)) {
+       if (!pmap_extract(pmap_kernel(), va_hi, &pa_hi)) {
                panic("%s: impossible, Page[UPAGES] unmapped", __func__);
        }
-       pmap_kremove(va, PAGE_SIZE);
-       uvm_pagefree(PHYS_TO_VM_PAGE(pa));
-
+       pmap_kremove(va_lo, PAGE_SIZE);
+       pmap_kremove(va_hi, PAGE_SIZE);
        pmap_update(pmap_kernel());
+       uvm_pagefree(PHYS_TO_VM_PAGE(pa_lo));
+       uvm_pagefree(PHYS_TO_VM_PAGE(pa_hi));
 
        return (void *)base;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.