From 06c78a98acccbfb7384dd4393cc0d3064a653006 Mon Sep 17 00:00:00 2001 From: mlarkin Date: Sat, 23 Jan 2021 22:34:46 +0000 Subject: [PATCH] vmm(4): wire faulted in pages This change wires the pages used by virtual machines managed by vmm(4). When uvm swaps out a page, vmm(4) does not properly do TLB flushing, possibly leading to memory corruption or improper page access later. While this diff is not the correct fix (implementing proper TLB flush semantics), it does work around the problem by not letting the pages get swapped out in the first place. This means that under memory pressure, swap pages will have to come from other processes, and it also means you cannot overcommit vmm(4) memory assignment (eg, assign more memory to VMs than you actually have). It is my plan to fix this the correct way, but that will take time. This issue was originally pointed out a long time ago by Maxime V., but due to my taking a year away from OpenBSD, the issue remained unfixed. --- sys/arch/amd64/amd64/vmm.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index a406a6cfe81..2f2fc66b984 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.274 2020/09/10 17:03:03 mpi Exp $ */ +/* $OpenBSD: vmm.c,v 1.275 2021/01/23 22:34:46 mlarkin Exp $ */ /* * Copyright (c) 2014 Mike Larkin * @@ -988,7 +988,7 @@ vmx_mprotect_ept(vm_map_t vm_map, paddr_t sgpa, paddr_t egpa, int prot) for (addr = sgpa; addr < egpa; addr += PAGE_SIZE) { pte = vmx_pmap_find_pte_ept(pmap, addr); if (pte == NULL) { - ret = uvm_fault(vm_map, addr, VM_FAULT_INVALID, + ret = uvm_fault(vm_map, addr, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) printf("%s: uvm_fault returns %d, GPA=0x%llx\n", @@ -5455,12 +5455,9 @@ svm_get_guest_faulttype(struct vmcb *vmcb) int svm_fault_page(struct vcpu *vcpu, paddr_t gpa) { - int fault_type, ret; - struct vmcb *vmcb = (struct vmcb *)vcpu->vc_control_va; - - fault_type = svm_get_guest_faulttype(vmcb); + int ret; - ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, fault_type, + ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) printf("%s: uvm_fault returns %d, GPA=0x%llx, rip=0x%llx\n", @@ -5512,20 +5509,9 @@ svm_handle_np_fault(struct vcpu *vcpu) int vmx_fault_page(struct vcpu *vcpu, paddr_t gpa) { - int fault_type, ret; - - fault_type = vmx_get_guest_faulttype(); - if (fault_type == -1) { - printf("%s: invalid fault type\n", __func__); - return (EINVAL); - } - - if (fault_type == VM_FAULT_PROTECT) { - vcpu->vc_exit.vee.vee_fault_type = VEE_FAULT_PROTECT; - return (EAGAIN); - } + int ret; - ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, fault_type, + ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, VM_FAULT_WIRE, PROT_READ | PROT_WRITE | PROT_EXEC); if (ret) -- 2.20.1