summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2009-05-13 07:42:53 +0000
committeralc <alc@FreeBSD.org>2009-05-13 07:42:53 +0000
commit2553ba9c6495ed3b8b92f21dc3c0eaee5e7fc188 (patch)
treecbac0558bc7205f8fe1f2e648d1126cbc3070955 /sys/i386
parent82da6bfdea2a3b999744f0b05506fe0e3a185061 (diff)
downloadFreeBSD-src-2553ba9c6495ed3b8b92f21dc3c0eaee5e7fc188.zip
FreeBSD-src-2553ba9c6495ed3b8b92f21dc3c0eaee5e7fc188.tar.gz
Correct a rare use-after-free error in pmap_copy(). This error was
introduced in amd64 revision 1.540 and i386 revision 1.547. However, it had no harmful effects until after a recent change, r189698, on amd64. (In other words, the error is harmless in RELENG_7.) The error is triggered by the failure to allocate a pv entry for the one and only mapping in a page table page. I am addressing the error by changing pmap_copy() to abort if either pv entry allocation or page table page allocation fails. This is appropriate because the creation of mappings by pmap_copy() is optional. They are a (possible) optimization, and not a requirement. Correct a nearby whitespace error in the i386 pmap_copy(). Crash reported by: jeff@ MFC after: 6 weeks
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/pmap.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 7f6900d..5f016d5 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -3638,7 +3638,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
dstmpte = pmap_allocpte(dst_pmap, addr,
M_NOWAIT);
if (dstmpte == NULL)
- break;
+ goto out;
dst_pte = pmap_pte_quick(dst_pmap, addr);
if (*dst_pte == 0 &&
pmap_try_insert_pv_entry(dst_pmap, addr,
@@ -3653,12 +3653,13 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
dst_pmap->pm_stats.resident_count++;
} else {
free = NULL;
- if (pmap_unwire_pte_hold( dst_pmap,
+ if (pmap_unwire_pte_hold(dst_pmap,
dstmpte, &free)) {
pmap_invalidate_page(dst_pmap,
addr);
pmap_free_zero_pages(free);
}
+ goto out;
}
if (dstmpte->wire_count >= srcmpte->wire_count)
break;
@@ -3667,6 +3668,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, vm_size_t len,
src_pte++;
}
}
+out:
sched_unpin();
vm_page_unlock_queues();
PMAP_UNLOCK(src_pmap);
OpenPOWER on IntegriCloud