New issue
Advanced search Search tips
Starred by 2 users
Status: Fixed
Owner:
Closed: May 2017
Cc:



Sign in to add a comment
MacOS: kernel register leak via 32-bit syscall exit
Project Member Reported by jannh@google.com, Feb 24 2017 Back to list
The XNU kernel, when compiled for a x86-64 CPU, can run 32-bit x86
binaries in compatibility mode. 32-bit binaries use partly separate
syscall entry and exit paths.

To return to userspace, unix_syscall() in bsd/dev/i386/systemcalls.c
calls thread_exception_return() (in osfmk/x86_64/locore.s), which in
turn calls return_from_trap, which is implemented in
osfmk/x86_64/idt64.s.

return_from_trap() normally branches into return_to_user relatively
quickly, which then, depending on the stack segment selector, branches
into either L_64bit_return or L_32bit_return. While the L_64bit_return
path restores all userspace registers, the L_32bit_return path only
restores the registers that are accessible in compatibility mode; the
registers r8 to r15 are not restored.

This is bad because, although switching to compatibility mode makes it
impossible to directly access r8..r15, the register contents are
preserved, and switching back to 64-bit mode makes the 64-bit
registers accessible again. Since the GDT always contains user code
segments for both compatibility mode and 64-bit mode, an unprivileged
32-bit process can leak kernel register contents as follows:

 - make a normal 32-bit syscall
 - switch to 64-bit mode (e.g. by loading the 64-bit user code segment
   using iret)
 - store the contents of r8..r15
 - switch back to compatibility mode (e.g. by loading the 32-bit user
   code segment using iret)

The attached PoC demonstrates the issue by dumping the contents of
r8..r15. Usage:

$ ./leakregs 
r8 = 0xffffff801d3872a8
r9 = 0xffffff8112abbec8
r10 = 0xffffff801f962240
r11 = 0xffffff8031d52bb0
r12 = 0x12
r13 = 0xffffff80094018f0
r14 = 0xffffff801cb59ea0
r15 = 0xffffff801cb59ea0

It seems like these are various types of kernel pointers, including
kernel text pointers.

If you want to compile the PoC yourself, you'll have to adjust the
path to nasm in compile.sh, then run ./compile.sh.

This bug was verified using the following kernel version:
15.6.0 Darwin Kernel Version 15.6.0: Mon Jan  9 23:07:29 PST 2017;
root:xnu-3248.60.11.2.1~1/RELEASE_X86_64 x86_64

This bug is subject to a 90 day disclosure deadline. After 90 days elapse
or a patch has been made broadly available, the bug report will become
visible to the public.
 
leakkregs.tar
15.0 KB Download
Project Member Comment 1 by jannh@google.com, Feb 24 2017
Labels: Id-660072038
Project Member Comment 2 by jannh@google.com, May 11 2017
Apple says the fix will be released May 15th, 2017.
Project Member Comment 3 by jannh@google.com, May 17 2017
Labels: CVE-2017-2509
Fixed in MacOS 10.12.5: https://support.apple.com/en-us/HT207797
Project Member Comment 4 by jannh@google.com, May 17 2017
Status: Fixed
Project Member Comment 5 by jannh@google.com, May 21 2017
Labels: -Reported-2017-Feb-24
Project Member Comment 6 by jannh@google.com, May 21 2017
Labels: -Restrict-View-Commit Reported-2017-Feb-24
Project Member Comment 7 by jannh@google.com, Jun 2
Labels: Methodology-source-review
Sign in to add a comment