An nice additional benefit of the recent Kernel Page Table Isolation (CONFIG_PAGE_TABLE_ISOLATION
) patches (to defend against CVE-2017-5754, the speculative execution “rogue data cache load” or “Meltdown” flaw) is that the userspace page tables visible while running in kernel mode lack the executable bit. As a result, systems without the SMEP CPU feature (before Ivy-Bridge) get it emulated for “free”.
Here’s a non-SMEP system with PTI disabled (booted with “pti=off
“), running the EXEC_USERSPACE
LKDTM test:
# grep smep /proc/cpuinfo # dmesg -c | grep isolation [ 0.000000] Kernel/User page tables isolation: disabled on command line. # cat <(echo EXEC_USERSPACE) > /sys/kernel/debug/provoke-crash/DIRECT # dmesg [ 17.883754] lkdtm: Performing direct entry EXEC_USERSPACE [ 17.885149] lkdtm: attempting ok execution at ffffffff9f6293a0 [ 17.886350] lkdtm: attempting bad execution at 00007f6a2f84d000
No crash! The kernel was happily executing userspace memory.
But with PTI enabled:
# grep smep /proc/cpuinfo # dmesg -c | grep isolation [ 0.000000] Kernel/User page tables isolation: enabled # cat <(echo EXEC_USERSPACE) > /sys/kernel/debug/provoke-crash/DIRECT Killed # dmesg [ 33.657695] lkdtm: Performing direct entry EXEC_USERSPACE [ 33.658800] lkdtm: attempting ok execution at ffffffff926293a0 [ 33.660110] lkdtm: attempting bad execution at 00007f7c64546000 [ 33.661301] BUG: unable to handle kernel paging request at 00007f7c64546000 [ 33.662554] IP: 0x7f7c64546000 ...
It should only take a little more work to leave the userspace page tables entirely unmapped while in kernel mode, and only map them in during copy_to_user()
/copy_from_user()
as ARM already does with ARM64_SW_TTBR0_PAN
(or CONFIG_CPU_SW_DOMAIN_PAN
on arm32).
© 2018, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.