Restore EPT protection checks on VMX when using VMM_IOC_MPROTECT_EPT
authordv <dv@openbsd.org>
Tue, 6 Apr 2021 00:19:58 +0000 (00:19 +0000)
committerdv <dv@openbsd.org>
Tue, 6 Apr 2021 00:19:58 +0000 (00:19 +0000)
A prior fix related to lack of TLB flushing accidentally removed the
fault type checks related to the access protection features available
via the VMM_IOC_MPROTECT_EPT ioctl. This restores the same logic for
checking the fault type and the exit to userland if the fault is due
to EPT access protections.

While here, update the comment for vmx_fault_page to accurately
reflect the various potential return values.

Reported by Adam Steen.

OK mlarkin@

sys/arch/amd64/amd64/vmm.c

index 0add6d3..ebf2bce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: vmm.c,v 1.279 2021/04/05 18:26:45 dv Exp $    */
+/*     $OpenBSD: vmm.c,v 1.280 2021/04/06 00:19:58 dv Exp $    */
 /*
  * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -5511,13 +5511,31 @@ svm_handle_np_fault(struct vcpu *vcpu)
  * Request a new page to be faulted into the UVM map of the VM owning 'vcpu'
  * at address 'gpa'.
  *
- * Returns EAGAIN to indication a protection fault, ie writing to a read only
- * page.
+ * Parameters:
+ *  vcpu: guest VCPU requiring the page to be faulted into the UVM map
+ *  gpa: guest physical address that triggered the fault
+ *
+ * Return Values:
+ *  0: if successful
+ *  EINVAL: if fault type could not be determined
+ *  EAGAIN: if a protection fault occurred, ie writing to a read-only page
+ *  errno: if uvm_fault(9) fails to wire in the page
  */
 int
 vmx_fault_page(struct vcpu *vcpu, paddr_t gpa)
 {
-       int ret;
+       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);
+       }
 
        ret = uvm_fault(vcpu->vc_parent->vm_map, gpa, VM_FAULT_WIRE,
            PROT_READ | PROT_WRITE | PROT_EXEC);