Module Name: src Committed By: martin Date: Tue Aug 15 09:44:09 UTC 2023
Modified Files: src/sys/uvm [netbsd-10]: uvm_fault.c Log Message: Pull up following revision(s) (requested by chs in ticket #327): sys/uvm/uvm_fault.c: revision 1.234 uvm: prevent TLB invalidation races during COW resolution When a thread takes a page fault which results in COW resolution, other threads in the same process can be concurrently accessing that same mapping on other CPUs. When the faulting thread updates the pmap entry at the end of COW processing, the resulting TLB invalidations to other CPUs are not done atomically, so another thread can write to the new writable page and then a third thread might still read from the old read-only page, resulting in inconsistent views of the page by the latter two threads. Fix this by removing the pmap entry entirely for the original page before we install the new pmap entry for the new page, so that the new page can only be modified after the old page is no longer accessible. This fixes PR 56535 as well as the netbsd versions of problems described in various bug trackers: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=225584 https://reviews.freebsd.org/D14347 https://github.com/golang/go/issues/34988 To generate a diff of this commit: cvs rdiff -u -r1.231 -r1.231.2.1 src/sys/uvm/uvm_fault.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_fault.c diff -u src/sys/uvm/uvm_fault.c:1.231 src/sys/uvm/uvm_fault.c:1.231.2.1 --- src/sys/uvm/uvm_fault.c:1.231 Wed Oct 26 23:27:32 2022 +++ src/sys/uvm/uvm_fault.c Tue Aug 15 09:44:09 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_fault.c,v 1.231 2022/10/26 23:27:32 riastradh Exp $ */ +/* $NetBSD: uvm_fault.c,v 1.231.2.1 2023/08/15 09:44:09 martin Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.231 2022/10/26 23:27:32 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_fault.c,v 1.231.2.1 2023/08/15 09:44:09 martin Exp $"); #include "opt_uvmhist.h" @@ -633,8 +633,17 @@ uvmfault_promote(struct uvm_faultinfo *u goto done; } - /* copy page [pg now dirty] */ + /* + * copy the page [pg now dirty] + * + * Remove the pmap entry now for the old page at this address + * so that no thread can modify the new page while any thread + * might still see the old page. + */ if (opg) { + pmap_remove(vm_map_pmap(ufi->orig_map), ufi->orig_rvaddr, + ufi->orig_rvaddr + PAGE_SIZE); + pmap_update(vm_map_pmap(ufi->orig_map)); uvm_pagecopy(opg, pg); } KASSERT(uvm_pagegetdirty(pg) == UVM_PAGE_STATUS_DIRTY);