Hypervisor-Protected Code Integrity (HVCI) is a method of preventing compromise of various kernel parts even when an attacker has compromised part of the kernel itself. While creating a Windbg extension for HyperV on Intel processors, the author noticed something very strange. Even with HVCI enabled some of the pages were marked RWX, which shouldn't be possible. On the 7 intel devices they had, 3 of them had this issue. Exploitation of the issue was trivial, since the pages were already marked RWX. So, what happened?
Intel Virtualization Extension (Intel VT-x) is a virtualization standard that's been upgraded multiple times. For IOMMU device memory protection, the memory can be exposed to the hypervisor in a few different ways, such VMEXIT, VmBus with HyperV and accelerated hardware mapped directly to the VM. To isolate memory between VMs, an IOMMU should have I/O device assignment, DMA remapping and handle interrupts in the appropriate VM.
When a remapping occurs, it must be announced in the BIOS by an APCI table called DMA Remapping Reporting (DMAR). If a device needs to perform DMA transfer on specific memory regions, like a network controller, it'll need access both before and after setting up the IOMMU. For these types of devices, there is another special table called the Reserved Memory Region Reporting (RMRR).
For RMRR structure, there are two important concepts. First, the BIOS should report memory described in the RMRR as Reserved in the UEFI memory map. Second, when the OS enables remapping, the address translation for these they need to be marked as RW. So, what's the bug in all of this?
The first point above (RMRR marked as Reserved in the MM) was simply not happening. When the secure kernel starts, it will go through each one of the marked pages to mark it as either RW or RX but not both. Since this page is never added, we have a problem. As a result, it leaves the execution protection for the memory region on, leading to a violation of HVCI.
To fix the issue, the commercial devices added RMRR to the memory map. Additionally, Windows removed the X permission on all RMRR memory regions in order to prevent this type of issue from happening in the future. Overall, an interesting root cause of a bug discovered by accident.