Index | Thread | Search

From:
Miguel Landaeta <miguel@miguel.cc>
Subject:
Re: vmm(4): return error for VMCALL instead of injecting #UD
To:
tech@openbsd.org
Date:
Mon, 16 Mar 2026 14:20:30 +0000

Download raw body.

Thread
On Mon, Mar 16, 2026 at 11:51:00AM +0000, Miguel Landaeta wrote:
> 
> Does this approach make sense, or is there a better way to handle this?

Sending a second revision. I realized that vmm(4) should continue
to inject #UD if the hypercall isn't from ring 0 (this case was missed
in the previous patch).


Index: sys/arch/amd64/amd64/vmm_machdep.c
===================================================================
RCS file: /home/cvs/src/sys/arch/amd64/amd64/vmm_machdep.c,v
diff -u -p -u -p -r1.72 vmm_machdep.c
--- sys/arch/amd64/amd64/vmm_machdep.c	16 Feb 2026 15:08:41 -0000	1.72
+++ sys/arch/amd64/amd64/vmm_machdep.c	16 Mar 2026 14:00:43 -0000
@@ -4301,8 +4301,15 @@ svm_handle_exit(struct vcpu *vcpu)
 		    vcpu->vc_gueststate.vg_rax == HVCALL_FORCED_ABORT)
 			return (EINVAL);
 		DPRINTF("SVM_VMEXIT_VMMCALL at cpl=%d\n", guest_cpl);
-		ret = vmm_inject_ud(vcpu);
-		update_rip = 0;
+		if (guest_cpl != 0) {
+			ret = vmm_inject_ud(vcpu);
+			update_rip = 0;
+			break;
+		}
+		/* Ring 0 unsupported hypercall - return error */
+		vcpu->vc_gueststate.vg_rax = -1;
+		vcpu->vc_gueststate.vg_rip += 3; /* VMMCALL is 3 bytes long */
+		update_rip = 1;
 		break;
 	default:
 		DPRINTF("%s: unhandled exit 0x%llx (pa=0x%llx)\n", __func__,
@@ -4741,8 +4748,15 @@ vmx_handle_exit(struct vcpu *vcpu)
 		    vcpu->vc_gueststate.vg_rax == HVCALL_FORCED_ABORT)
 			return (EINVAL);
 		DPRINTF("VMX_EXIT_VMCALL at cpl=%d\n", guest_cpl);
-		ret = vmm_inject_ud(vcpu);
-		update_rip = 0;
+		if (guest_cpl != 0) {
+			ret = vmm_inject_ud(vcpu);
+			update_rip = 0;
+			break;
+		}
+		/* Ring 0 unsupported hypercall - return error */
+		vcpu->vc_gueststate.vg_rax = -1;
+		vcpu->vc_gueststate.vg_rip += 3; /* VMCALL is 3 bytes long */
+		update_rip = 1;
 		break;
 	default:
 #ifdef VMM_DEBUG