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