NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

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



>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;
 }




Home | Main Index | Thread Index | Old Index