Download raw body.
vmm(4): return error for VMCALL instead of injecting #UD
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
vmm(4): return error for VMCALL instead of injecting #UD