Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Feb 2021 20:52:06 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 5966aae9c7c2 - stable/13 - pmap: Fix largemap restart checks in the kernel_maps sysctl handler
Message-ID:  <202102282052.11SKq6rp081337@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=5966aae9c7c25707c785ec056cb8462a037a480e

commit 5966aae9c7c25707c785ec056cb8462a037a480e
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-02-25 23:49:47 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-02-28 20:51:51 +0000

    pmap: Fix largemap restart checks in the kernel_maps sysctl handler
    
    The purpose of these checks is to ensure that the address of the
    next-level page table page is valid, since nothing is synchronizing with
    a concurrent update of the large map and large map PTPs are freed to the
    system.  However, if PG_PS is set, there is no next level.
    
    Reported by:    rpokala
    Reviewed by:    kib
    Tested by:      rpokala
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D28922
    
    (cherry picked from commit aac25e222525780db8939d07a594d3e090c0a148)
---
 sys/amd64/amd64/pmap.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 0e1d1c02d1fc..bd23fd176e88 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -11349,9 +11349,6 @@ restart:
 				continue;
 			}
 			pa = pdpe & PG_FRAME;
-			if (PMAP_ADDRESS_IN_LARGEMAP(sva) &&
-			    vm_phys_paddr_to_vm_page(pa) == NULL)
-				goto restart;
 			if ((pdpe & PG_PS) != 0) {
 				sva = rounddown2(sva, NBPDP);
 				sysctl_kmaps_check(sb, &range, sva, pml4e, pdpe,
@@ -11360,6 +11357,15 @@ restart:
 				sva += NBPDP;
 				continue;
 			}
+			if (PMAP_ADDRESS_IN_LARGEMAP(sva) &&
+			    vm_phys_paddr_to_vm_page(pa) == NULL) {
+				/*
+				 * Page table pages for the large map may be
+				 * freed.  Validate the next-level address
+				 * before descending.
+				 */
+				goto restart;
+			}
 			pd = (pd_entry_t *)PHYS_TO_DMAP(pa);
 
 			for (k = pmap_pde_index(sva); k < NPDEPG; k++) {
@@ -11371,9 +11377,6 @@ restart:
 					continue;
 				}
 				pa = pde & PG_FRAME;
-				if (PMAP_ADDRESS_IN_LARGEMAP(sva) &&
-				    vm_phys_paddr_to_vm_page(pa) == NULL)
-					goto restart;
 				if ((pde & PG_PS) != 0) {
 					sva = rounddown2(sva, NBPDR);
 					sysctl_kmaps_check(sb, &range, sva,
@@ -11382,6 +11385,15 @@ restart:
 					sva += NBPDR;
 					continue;
 				}
+				if (PMAP_ADDRESS_IN_LARGEMAP(sva) &&
+				    vm_phys_paddr_to_vm_page(pa) == NULL) {
+					/*
+					 * Page table pages for the large map
+					 * may be freed.  Validate the
+					 * next-level address before descending.
+					 */
+					goto restart;
+				}
 				pt = (pt_entry_t *)PHYS_TO_DMAP(pa);
 
 				for (l = pmap_pte_index(sva); l < NPTEPG; l++,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202102282052.11SKq6rp081337>