svn commit: r202837 - in stable/7/sys: amd64/amd64 i386/i386

John Baldwin jhb at FreeBSD.org
Fri Jan 22 21:23:09 UTC 2010


Author: jhb
Date: Fri Jan 22 21:23:09 2010
New Revision: 202837
URL: http://svn.freebsd.org/changeset/base/202837

Log:
  MFC 189698,192035:
  Optimize the inner loop of pmap_copy().
  
  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().

Modified:
  stable/7/sys/amd64/amd64/pmap.c
  stable/7/sys/i386/i386/pmap.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/amd64/amd64/pmap.c
==============================================================================
--- stable/7/sys/amd64/amd64/pmap.c	Fri Jan 22 20:52:31 2010	(r202836)
+++ stable/7/sys/amd64/amd64/pmap.c	Fri Jan 22 21:23:09 2010	(r202837)
@@ -3555,6 +3555,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 
 		src_pte = (pt_entry_t *)PHYS_TO_DMAP(srcptepaddr);
 		src_pte = &src_pte[pmap_pte_index(addr)];
+		dstmpte = NULL;
 		while (addr < va_next) {
 			pt_entry_t ptetemp;
 			ptetemp = *src_pte;
@@ -3562,10 +3563,12 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 			 * we only virtual copy managed pages
 			 */
 			if ((ptetemp & PG_MANAGED) != 0) {
-				dstmpte = pmap_allocpte(dst_pmap, addr,
-				    M_NOWAIT);
-				if (dstmpte == NULL)
-					break;
+				if (dstmpte != NULL &&
+				    dstmpte->pindex == pmap_pde_pindex(addr))
+					dstmpte->wire_count++;
+				else if ((dstmpte = pmap_allocpte(dst_pmap,
+				    addr, M_NOWAIT)) == NULL)
+					goto out;
 				dst_pte = (pt_entry_t *)
 				    PHYS_TO_DMAP(VM_PAGE_TO_PHYS(dstmpte));
 				dst_pte = &dst_pte[pmap_pte_index(addr)];
@@ -3588,6 +3591,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 					 	    addr);
 				    	    	pmap_free_zero_pages(free);
 					}
+					goto out;
 				}
 				if (dstmpte->wire_count >= srcmpte->wire_count)
 					break;
@@ -3596,6 +3600,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 			src_pte++;
 		}
 	}
+out:
 	vm_page_unlock_queues();
 	PMAP_UNLOCK(src_pmap);
 	PMAP_UNLOCK(dst_pmap);

Modified: stable/7/sys/i386/i386/pmap.c
==============================================================================
--- stable/7/sys/i386/i386/pmap.c	Fri Jan 22 20:52:31 2010	(r202836)
+++ stable/7/sys/i386/i386/pmap.c	Fri Jan 22 21:23:09 2010	(r202837)
@@ -3673,7 +3673,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 				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,
@@ -3688,12 +3688,13 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 					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;
@@ -3702,6 +3703,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
 			src_pte++;
 		}
 	}
+out:
 	sched_unpin();
 	vm_page_unlock_queues();
 	PMAP_UNLOCK(src_pmap);


More information about the svn-src-stable-7 mailing list