4 ms·
Cute but extremely risky. The kernel has access to all memory-mapped devices and all weird privileged mode instructions, and the nested kernel has to ensure th
by comex 12y ago
Cute but extremely risky. The kernel has access to all memory-mapped devices and all weird privileged mode instructions, and the nested kernel has to ensure that the IOMMU is safe and no instructions that can turn off paging, modify the page tables, etc. appear at any offset within the code, including unaligned. Which also means that even if working around coincidental unaligned instances of such instructions is easy in practice, as stated in the paper, there's always a chance some (code, compiler) version combination will randomly fail to compile and (even if this is hypothetically made to work automatically most of the time) possibly require manual intervention...
So, have they missed any such instructions? To be fair, they are assuming the original kernel modules are trustworthy but have been compromised at runtime, so these would have to appear either for another reason or by chance in the kernel, but ... off the top of my head:
- Hardware breakpoints/watchpoints in the inner kernel or at the CR0 writing instruction.
- - Or hoping/somehow ensuring the CPU gets an IRQ or something right after executing the PG0 write. Problematic, but not out of the question.
- - This could be partially negated by ensuring that like the PG0 enabler, the fault handlers are mapped at an address that corresponds to a physical address containing a trap. But I don't think this is sufficient, 'cause... now that paging is disabled and so you can write to code, you should be able to set the stack pointer in the TSS to overwrite the handler!
- Hardware VM support. I checked the Intel manual: the VMCS structure points to some addresses that map guest physical addresses to real physical addresses, so this really needs to be disabled. (Also, the VMCLEAR instruction, which requires VMXON first, writes directly to physical addresses.) There's also whatever AMD does.
And with a bit more manual reading - but I could be wrong on these:
- Switching to 32-bit mode and confusing the inner kernel that way.
- Switching to 32-bit mode and then using hardware task switching to load CR3.
Those two only require the iret instruction!
Based on scanner-objdump.py, they seem to only be checking for movs to cr{0,2,3} and wrmsr, so all of the above should work. I'm not an x86 expert, so (a) some of the above may be wrong, but (b) there are probably more potential avenues I don't know about. :)
- bcg1 12y agoI'm not being sarcastic, this is a serious question because the specifics of this are over my head Are you saying that the "nested kernel" architecture technically increases the surface area for attack, or is the problem that it gives a false sense of security compared to what it actually provides?
- comex 12y agoThe latter. There's no obvious reason it would decrease security, but if the main kernel is compromised, the inner kernel's security model is really hard to enforce correctly against an opponent which is also running in ring 0.
- comex 12y agoCorrection (self-reply): Switching to 32-bit mode won't work - or could be easily prevented at any rate: you can't switch directly to real 32-bit mode ("legacy mode"), only to "compatibility mode" where the page table format stays the same, and task switching isn't supported. Switching to legacy mode requires a wrmsr, which is blocked. Even if there was a benefit to going into compatibility mode with kernel privileges, once there you're limited to the bottom 4GB of the address space, which would normally be reserved for user mode, and since SMEP is forced on you can't execute user pages in kernel mode. So the inner kernel just needs to prevent any executable kernel pages from being mapped below 4GB. Told you I wasn't an x86 expert. But the other points stand. ...though in the current implementation the inner kernel doesn't block the relevant MSR write, so it may be possible anyway, although the manual says you're supposed to disable paging first, which is blocked. In any case, this, along with the hardware VM thing (since VMX can be disabled in cr4), would be easy to fix. I'm not so sure about the interrupt approach.