Replace KASSERT in uvm_fault_unwire_locked() with code that handles the
authorkettenis <kettenis@openbsd.org>
Mon, 4 Apr 2022 09:27:05 +0000 (09:27 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 4 Apr 2022 09:27:05 +0000 (09:27 +0000)
case where not all pages are wired.  The KASSERT can be triggered in
multi-threaded applications when a thread calling munmap(2) races another
thread that invokes sysctl(2).  Properly written code shouldn't do this,
but making the kernel crash in this case is a bit harsh.

ok gezdo@, deraadt@

Fixes:
Reported-by: syzbot+e8310909e2910c9cca08@syzkaller.appspotmail.com
sys/uvm/uvm_fault.c

index a506372..56a30dc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_fault.c,v 1.128 2022/02/11 09:25:04 kn Exp $      */
+/*     $OpenBSD: uvm_fault.c,v 1.129 2022/04/04 09:27:05 kettenis Exp $        */
 /*     $NetBSD: uvm_fault.c,v 1.51 2000/08/06 00:22:53 thorpej Exp $   */
 
 /*
@@ -1638,12 +1638,16 @@ uvm_fault_unwire_locked(vm_map_t map, vaddr_t start, vaddr_t end)
                 * find the map entry for the current address.
                 */
                KASSERT(va >= entry->start);
-               while (va >= entry->end) {
+               while (entry && va >= entry->end) {
                        next = RBT_NEXT(uvm_map_addr, entry);
-                       KASSERT(next != NULL && next->start <= entry->end);
                        entry = next;
                }
 
+               if (entry == NULL)
+                       return;
+               if (va < entry->start)
+                       continue;
+
                /*
                 * lock it.
                 */
@@ -1670,7 +1674,7 @@ uvm_fault_unwire_locked(vm_map_t map, vaddr_t start, vaddr_t end)
        }
 
        if (oentry != NULL) {
-               uvm_map_unlock_entry(entry);
+               uvm_map_unlock_entry(oentry);
        }
 }