|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [BUG]: Crashing Xen when nestedhvm is enabled
Dear all,
I think I have found a way for a guest to crash the hypervisor,
when hardware nesting is enabled and we are running on Intel using VMX.
This is done by executing the following steps in the non nested guest:
- Enable VMX and set a vmcs active
- Override the revision id of the active vmcs using memory access to any
invalid id
- call vmwrite to write the `MSR_BITMAP`
Basically this:
```C
vmxon();
vmcs = alloc();
*(uint32_t*)vmcs = correct_vmcs_revision_id;
vmptrld(vmcs);
*vmcs = invalide_vmcs_revision_id;
vmwrite(MSR_BITMAP, NULL);
```
The `vmptrld` will set the provided vmcs as the link pointer as seen in
`xen/arch/x86/hvm/vmx/vvmx.c:1834`
```
if ( cpu_has_vmx_vmcs_shadowing )
nvmx_set_vmcs_pointer(v, nvcpu->nv_vvmcx);
```
If the guest now calls `VMWRITE` it will access that vmcs directly,
execpt if writing/reading the `IO_BITMAP` or the `MSR_BITMAP`
`xen/arch/x86/hvm/vmx/vvmx.c:107`
```
/*
* For the following 6 encodings, we need to handle them in VMM.
* Let them vmexit as usual.
*/
set_bit(IO_BITMAP_A, vw);
set_bit(VMCS_HIGH(IO_BITMAP_A), vw);
set_bit(IO_BITMAP_B, vw);
set_bit(VMCS_HIGH(IO_BITMAP_B), vw);
set_bit(MSR_BITMAP, vw);
set_bit(VMCS_HIGH(MSR_BITMAP), vw);
```
If we now execute `vmwrite(MSR_BITMAP, 0)` in the guest it will execute this
stack:
```
nvmx_handle_vmwrite
set_vvmcs_safe
set_vvmcs_real_safe
virtual_vmcs_vmwrite_safe
virtual_vmcs_enter
__vmptrld
```
The vmcs pointer being loaded in the last step being the one supplied by the
guest
that has been overwritten.
Since we have overwritten the `vmcs_revision_id` the hardware will reject the
vmptrld, which
will call `BUG()`.
---
A secondary similar bug happens when calling `VMXOFF` while a shadow vmcs is
active.
This will not clear the shadow vmcs, and crash the guest if it ever writes to
the vmcs again.
Effectively locking the page of being modified until a new vmcs is set active.
This should be fixed by applying this patch:
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 2432af58e0..3895dd158a 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1589,6 +1589,8 @@ static int nvmx_handle_vmxoff(struct cpu_user_regs *regs)
struct vcpu *v=current;
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
+ if ( cpu_has_vmx_vmcs_shadowing )
+ nvmx_clear_vmcs_pointer(v, nvcpu->nv_vvmcx);
nvmx_purge_vvmcs(v);
nvmx->vmxon_region_pa = INVALID_PADDR;
As far as I have read it is not specifically stated in the Intel SDM that a
VMXOFF clears the active vmcs, however it
does also not state anything otherwise and I thinks it's saner to clear it than
to crash the guest because of an
vmcs error, when it has vmx disabled.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |