Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 13 Feb 2023 21:35:56 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d0991948182a - main - vm_fault: Fix a race in vm_fault_soft_fast()
Message-ID:  <202302132135.31DLZuMh099084@gitrepo.freebsd.org>

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

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

commit d0991948182a1a149ee84f1b9c4d3e30450c8f0b
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-02-13 21:24:40 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-02-13 21:35:47 +0000

    vm_fault: Fix a race in vm_fault_soft_fast()
    
    When vm_fault_soft_fast() creates a mapping, it release the VM map lock
    before unbusying the top-level object.  Without the map lock, however,
    nothing prevents the VM object from being deallocated while still busy.
    
    Fix the problem by unbusying the object before releasing the VM map
    lock.  If vm_fault_soft_fast() fails to create a mapping, the VM map
    lock is not released, so those cases don't need to change.
    
    Reported by:    syzkaller
    Reviewed by:    kib (previous version)
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D38527
---
 sys/vm/vm_fault.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 959e67b88a38..87c15e972279 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -338,20 +338,16 @@ vm_fault_soft_fast(struct faultstate *fs)
 #endif
 	int psind;
 	vm_offset_t vaddr;
-	enum fault_status res;
 
 	MPASS(fs->vp == NULL);
 
-	res = FAULT_SUCCESS;
 	vaddr = fs->vaddr;
 	vm_object_busy(fs->first_object);
 	m = vm_page_lookup(fs->first_object, fs->first_pindex);
 	/* A busy page can be mapped for read|execute access. */
 	if (m == NULL || ((fs->prot & VM_PROT_WRITE) != 0 &&
-	    vm_page_busied(m)) || !vm_page_all_valid(m)) {
-		res = FAULT_FAILURE;
-		goto out;
-	}
+	    vm_page_busied(m)) || !vm_page_all_valid(m))
+		goto fail;
 	m_map = m;
 	psind = 0;
 #if VM_NRESERVLEVEL > 0
@@ -386,10 +382,8 @@ vm_fault_soft_fast(struct faultstate *fs)
 #endif
 	if (pmap_enter(fs->map->pmap, vaddr, m_map, fs->prot, fs->fault_type |
 	    PMAP_ENTER_NOSLEEP | (fs->wired ? PMAP_ENTER_WIRED : 0), psind) !=
-	    KERN_SUCCESS) {
-		res = FAULT_FAILURE;
-		goto out;
-	}
+	    KERN_SUCCESS)
+		goto fail;
 	if (fs->m_hold != NULL) {
 		(*fs->m_hold) = m;
 		vm_page_wire(m);
@@ -398,12 +392,13 @@ vm_fault_soft_fast(struct faultstate *fs)
 		vm_fault_prefault(fs, vaddr, PFBAK, PFFOR, true);
 	VM_OBJECT_RUNLOCK(fs->first_object);
 	vm_fault_dirty(fs, m);
+	vm_object_unbusy(fs->first_object);
 	vm_map_lookup_done(fs->map, fs->entry);
 	curthread->td_ru.ru_minflt++;
-
-out:
+	return (FAULT_SUCCESS);
+fail:
 	vm_object_unbusy(fs->first_object);
-	return (res);
+	return (FAULT_FAILURE);
 }
 
 static void



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