8

For SVM or VT-x, the set of conditions which trigger a vmexit to the virtual machine monitor is pretty complex. Can an unprivileged process trigger any of these without assistance from the kernel? The documentation for VMMCALL and VMCALL both say they only work in ring 0, so I assume they're OK.

This is a followup question to Ninefinger's excellent response the other day. There was so much detail there, it has taken a while for me to assimilate. :)

Harry Collins
  • 165
  • 2
  • 6

2 Answers2

10

What you need to understand instructions are the Intel software Developer Manuals. For what it's worth, I sometimes find them a bit opaque - so I contrast what I read on google and in the AMD Manuals as they both implement the x86/x64 architecture.

Specifically, for this you need Vol 3C: Virtualisation. As of the current manual you want page 293 ("VMCALL—Call to VM Monitor"). In there, you have this helpful expression:

IF not in VMX operation
    THEN #UD;
ELSIF in VMX non-root operation
    THEN VM exit;
ELSIF (RFLAGS.VM = 1) or (IA32_EFER.LMA = 1 and CS.L = 0)
    THEN #UD;
ELSIF CPL > 0
    THEN #GP(0);
...

Translation into English: #GP is a general protection exception, CPL is the current privilege level. VMX non-root operation is:

There are two kinds of VMX operation: VMX root operation and VMX non-root operation. In general, a VMM will run in VMX root operation and guest software will run in VMX non-root operation.

So, that would imply that VMCall instructions can be issued from any privilege level on the guest. The ring 0 requirement only applies to the host system. However, I caveat that with a disclaimer - see my implications bulletpoints in a minute.

Crazily insane I know. Apparently, however, it's true. Have a read of this thread where KVM kernel devs are discussing exactly this. The KVM patch in question did this:

kvm_get_segment(vcpu,&cs, VCPU_SREG_CS);
if (cs.dpl != 0) {
    ret = -KVM_EPERM;
    goto out;
}

Which considers the "hypercall" invalid if not made from guest ring 0.

Implications:

  1. Any guest level code can issue a VMCall. However, from the very preliminary reading I've done it seems as though it (might) might be impossible for that to be useful in any way - as ring 3 addresses would presumably be virtual w.r.t the guest operating system (and therefore mean nothing to the host). I strongly suspect this is the case, but I cannot (yet) confirm it.
  2. If you think about it this makes sense - if guest level code triggers some other kind of VM Exit you want the VMM to take over.
  3. However, I suspect many hypervisors implement the above restriction - ring 0 guest only, or some other conditions on the hypercall API they apply.
  4. However, they may not.

So, what you need to do if you really want to dig into it is verify:

  • What hypercalls, if any, your VMM supports.
  • What conditions they consider a hypercall valid. As I say, I expect the VMCall will be restricted to guest ring 0 only.

If it is the case that VMCall et al can only be meaningfully executed from ring 0, then your client-side guest code must be able to execute in ring 0 too, or persuade some of your existing code to do something it shouldn't. For example:

  1. You can persuade the kernel to execute an arbitrary piece of code that contains the VMCall to do whatever it is you want.
  2. You persuade an existing driver that uses a VMCall to make that call your way i.e. with your arguments, rather than the ones it might ordinarily use.

The success of that for an exploit depends entirely on the hypervisor and if those VMCalls are vulnerable or not. If they're not, it doesn't matter whether you managed to call them - the hypervisor can reject them as appropriate. At this point, I honestly don't think this exploit route (through a VMCall) is very likely (although the consequences are of course pretty severe if there were one).

Two things I've missed here:

  • There are many other triggers for VM Exits. Can guest processes cause them? Not programmatically I don't think - they happen because of something the guest is doing (conditions for exits supplied by the VMM) rather than in direct response to an opcode.
  • Again, "breaking out" of a VM is a loose term. Users of virtual machines should also be wary of things like network emulation - if your guest and host can talk to each other over TCP/IP and your host IP stack has a vulnerability in it and code on the guest can exploit it - you could still be compromised. Likewise, transferring files from guest to host carries an inherent risk.
  • 1
    Thanks again for the clarification. It appears(*) that vbox only checks the guest CPL when patching the guest machine code. That really ruins my day, but better to know than to be ignorant. – Harry Collins Dec 20 '11 at 17:07
  • (*) (Judging from the fact that `CPUMGetGuestCPL` only appears under `#ifdef VBOX_HWACCM_WITH_GUEST_PATCHING` in `VMXR0RunGuestCode`. Haven't checked the SVM source code.) – Harry Collins Dec 20 '11 at 17:08
  • 1
    Indeed - no problem. As I say - I'm not 100% on whether ring 3 code can make a sensible VMCall. I need to look very carefully at the mechanisms involved. So I wouldn't worry too much about it - remember, the fact a VMCall can be triggered is not the end of the world most of the time, unless there are issues in the hypervisor, you shouldn't be able to break out. I am, however, intrigued as to what you can do to the guest - you've given me something to look at at the weekend :) –  Dec 20 '11 at 17:19
  • 1
    Actually, vbox does check the CPL in other places, such as `IOMInterpretCheckPortIOAccess`, but now it's very much "maze of twisty little passages" territory. Will be interested to hear the results of any weekend research you squeeze in this weekend. :) – Harry Collins Dec 20 '11 at 17:28
4

Yes, unprivileged guest code can trigger a VM exit.

However, this does not mean that unprivileged guest code can break out of the VM. When a VM exit is triggered, control is transferred to the code of the virtual machine monitor. If the VMM code is written correctly, it is responsible for handling the VM exit safely: and in particular, in a way that does not allow malicious guest code to break out of the VM.

Please note that a "VM exit" is a technical term, which refers to transferring control to the VMM. Despite the use of the word "exit", it does not imply that the guest code can break out of the VM. It's referring to a way of invoking the VMM, not some sort of security breach. If the VMM is free of security vulnerabilities, then guest code cannot break out of the VM, regardless of whether it is executing in ring 0 (in the guest) or in unprivileged mode.

Thus, while the answer to your question is yes, it is much less dangerous than it might at first appear.

D.W.
  • 98,420
  • 30
  • 267
  • 572