Linux 3.17 guest-triggerable KVM OOPS

2014.10.24
Risk: Medium
Local: Yes
Remote: No
CWE: N/A

On Linux 3.17, a KVM guest can trigger a NULL pointer dereference by forcing the host to emulate certain well-formed RIP-relative instructions or certain types of corrupt or page-straddling instructions. This is almost certainly just a DoS -- there is a single read-modify-write to the NULL pointer, and no kernel code will consume data loaded from the NULL pointer if something is mapped there. The bugs, or at least dangerous code, arguably existed in much older kernels, but the NULL pointer dereference was introduced in 41061cdb98a0bec464278b4db8e894a3121671f5, which is only present in 3.17. To fix it, you can either revert the broken patch or you can apply both patches here as well as the attached patch: http://thread.gmane.org/gmane.comp.emulators.kvm.devel/128427 (NB: I'm not sure whether "Emulator does not decode clflush well" is necessary.) Details: Depending on your point of view, there are either one or two bugs here. Nadav Amit discovered an error in the instruction decoder that would cause certain RIP-relative instructions to OOPS the decoder. Specifically, rather than adding RIP to the operand address, RIP would be added to *0 from the host's perspective. I wrote an ugly proof-of-concept to trigger it (kvm_clflush_oops.c, although I've cleaned it up somewhat since I originally wrote it). That PoC only works on an SMP guest, and only when run as root. I also discovered that Nadav's fix was incomplete (or that there was another bug, depending on your perspective). Certain invalid instructions (due to multiple error cases, including a failure to fetch part of the instruction or due to the instruction being too long) could trigger the same NULL pointer dereference. Nadav wrote an extremely elegant PoC that exploits this buggy error handling, reproduced with permission below. This PoC doesn't require SMP or privilege; it's just crashes the host directly. Figuring out how it works is left as an exercise to the reader (hint: it might not work on Atom hosts). Please assign one or two CVEs as appropriate. (And, if you're hosting untrusted code on a Linux 3.17 host, patch your system!) #include <sys/mman.h> #include <stdlib.h> #include <string.h> int main() { void *mem = mmap(NULL, 8192, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_POPULATE, -1, 0); memcpy((char*)mem + 0xff3, "\xf0\x65\x65\x65\x65\x65\x65\x0f\x38\xf1" "\x05\x00\x00\x00\x00\x00", 15); asm volatile(&#8220;jmp *%0\n\t&#8221; : : "r" (mem+0xff3)); return 0; } --Andy

References:

http://seclists.org/oss-sec/2014/q4/att-427/kvm_fix.patch
http://seclists.org/oss-sec/2014/q4/430


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top