Skip to content
March 10, 2015 / Rafal Wojtczuk

The five Xen Security Advisories from March 2015 and Bromium vSentry

Five Xen hypervisor security advisories – XSA-120, XSA-121, XSA-122, XSA-123 and XSA-124 have been published recently. Let’s have a look how they relate to the Bromium vSentry hypervisor, uXen, that has been derived from Xen.

Summary of impact on uXen

XSA-120 – not vulnerable
XSA-121 – minor data disclosure
XSA-122 – minor data disclosure
XSA-123 – not vulnerable
XSA-124 – not vulnerable

XSA-120 and XSA-124

These vulnerabilities are related to PCI-passthrough functionality. If a malicious VM has been granted direct access to a PCI device, it can crash the host. Currently, in Bromium vSentry we do not pass any PCI devices to any VM, therefore these vulnerabilities are not relevant.

XSA-121

The code responsible for emulation of some hardware (e.g. real-time clock, interrupt controller) refuses to handle unexpected requests from the VM. Unfortunately, the upper layers of the emulator still return 4 bytes of uninitialized data to the VM, despite the fact that this location has not been filled by the lower layer of the code. This results in a limited information disclosure – four bytes from the hypervisor address space are disclosed to the VM. These four bytes reside in the hypervisor stack. Therefore, the impact is minimal – the only information useful for an attacker is the partial value of pointers residing on the stack. This is not interesting by itself, but it might be helpful when exploiting another (unrelated) vulnerability based on memory corruption, because it makes ASLR protection ineffective.
uXen is potentially vulnerable to this issue.

XSA-122

This issue is very similar to XSA-121. This time, limited information disclosure of the contents of the hypervisor’s stack occurs when handling the “xen_version” hypercall. The impact is also identical to XSA-121 (the difference is that more than 4 bytes can be disclosed).
uXen is potentially vulnerable to this issue.

XSA-123

This is the most interesting one of the four, because this is a hypervisor memory corruption. The discoverer’s analysis is here; the below independent analysis is essentially the same, with a few extra bits on the CPU0 case.
The vulnerability lies in the code responsible for instruction emulation. The Xen emulator maintains the following data structure (C union):
union {
/* OP_REG: Pointer to register field.*/
unsigned long *reg;
/* OP_MEM: Segment and offset. */
struct { enum x86_segment seg; unsigned long off; } mem;
};

If the instruction accesses memory, then the “mem” field of the union should be used. If the instruction accesses a register, then the “reg” pointer should be used – it points to the stored register on the hypervisor stack. The problem arises when Xen emulates an instruction that does not access memory, but is prefixed by the segment override prefix (naturally, such a combination does not make sense). In such case, the “reg” pointer is first initialized to a legal location, but then the “mem.seg” field is also written to. As both fields (“reg” and “seg”) share the same location (this is how C unions work), the result is that the “reg” pointer is corrupted. Subsequently, this pointer is read or written to with a controllable value.
The crucial limitation is that the “reg” pointer is 8 bytes long (assuming x86-64 architecture) and the “seg” field is 4 bytes long (unless “–short-enums” option is passed to the compiler, but it seems to not be the case at least by default). It means that only the low 4 bytes of “reg” can be controlled, and with a very limited range of values. The biggest possible value of “enum x86_segment” type, that can be a prefix, is 5. If the original value of “reg” was 0xXXXXXXXXYYYYYYYY, we can turn it to 0xXXXXXXXX0000000Z, where Z is in 0-5 range (and the high 32 bits are unchanged). Initially, the “reg” field points to the hypervisor stack. In order to understand the impact, we need to know the possible ranges of the hypervisor stack locations. The following information was gathered on Xen-4.4.1 x86-64 system (particularly, the file xen-4.4.1/xen/include/asm-x86/config.h is very helpful). There are two cases:
1) An attacker controls a VM that can run on physical CPU 0. The stack for CPU 0 resides in the Xen image bss section, so it is located at an address a bit higher than 0xffff82d080000000. After overwrite, this pointer will have the value 0xffff82d00000000Z (again, 0<=Z<=5). This virtual address is mapped and belongs to the compatibility machine-to-phys translation table. This data structure is used only for PV VMs (while the vulnerability can only be triggered from a HVM), therefore (most likely) an attacker needs to control both a PV VM and a HVM to proceed. Even in this case, it is unclear how an ability to control the first entry in machine-to-phys translation table can help an attacker.
2) An attacker controls a VM that cannot run on physical CPU 0. Hypervisor stacks for CPUs other than 0 are allocated on the Xen heap. The typical address of the stack top is 0xffff830000000000+physical_memory_size-something_small, because memory for CPU stacks are allocated early at the Xen boot time, from the top of physical memory (and all physical memory is mapped at the virtual address 0xffff830000000000). After the vulnerability is triggered, the “reg” pointer will have the value 0xffff830V0000000Z, where again 0<=Z<=5, and V=(int)(physical_memory_size_in_GB/4.0). This address is mapped to a single physical frame that can serve any purpose – e.g. can be used by dom0 kernel to store crucial pointers. However, it is nontrivial for a malicious VM to force the hypervisor to allocate this frame in a way that would result in reliable privilege escalation. On the other hand, uncontrolled memory corruption in another VM (limited to a single page) is likely.
The good news is that uXen is not vulnerable to this issue. We identified the Xen instruction emulator as a possible attack target a long time ago, and its functionality in uXen is severely limited. Particularly, uXen (when running a microVM) refuses to emulate an instruction with a segment override – if such an instruction is seen, the microVM is killed.

%d bloggers like this: