Author: alc
Date: Wed May 13 07:42:53 2009
New Revision: 192035
URL: http://svn.freebsd.org/changeset/base/192035

Log:
  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

Modified:
  head/sys/amd64/amd64/pmap.c
  head/sys/i386/i386/pmap.c

Modified: head/sys/amd64/amd64/pmap.c
==============================================================================
--- head/sys/amd64/amd64/pmap.c Wed May 13 05:39:39 2009        (r192034)
+++ head/sys/amd64/amd64/pmap.c Wed May 13 07:42:53 2009        (r192035)
@@ -3556,7 +3556,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
                                        dstmpte->wire_count++;
                                else if ((dstmpte = pmap_allocpte(dst_pmap,
                                    addr, M_NOWAIT)) == NULL)
-                                       break;
+                                       goto out;
                                dst_pte = (pt_entry_t *)
                                    PHYS_TO_DMAP(VM_PAGE_TO_PHYS(dstmpte));
                                dst_pte = &dst_pte[pmap_pte_index(addr)];
@@ -3579,6 +3579,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;
@@ -3587,6 +3588,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: head/sys/i386/i386/pmap.c
==============================================================================
--- head/sys/i386/i386/pmap.c   Wed May 13 05:39:39 2009        (r192034)
+++ head/sys/i386/i386/pmap.c   Wed May 13 07:42:53 2009        (r192035)
@@ -3638,7 +3638,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,
@@ -3653,12 +3653,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;
@@ -3667,6 +3668,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pm
                        src_pte++;
                }
        }
+out:
        sched_unpin();
        vm_page_unlock_queues();
        PMAP_UNLOCK(src_pmap);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to