From 9c0836ce97ae36165abd8eb5241bb5239af3a756 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 1 Jan 2020 13:02:32 +0100 Subject: [PATCH] Kernel: Enable x86 UMIP (User Mode Instruction Prevention) if supported This prevents code running outside of kernel mode from using the following instructions: * SGDT - Store Global Descriptor Table * SIDT - Store Interrupt Descriptor Table * SLDT - Store Local Descriptor Table * SMSW - Store Machine Status Word * STR - Store Task Register There's no need for userspace to be able to use these instructions so let's just disable them to prevent information leakage. --- Base/usr/share/man/man1/crash.md | 1 + Kernel/Arch/i386/CPU.cpp | 2 ++ Kernel/Arch/i386/CPU.h | 1 + Kernel/init.cpp | 8 ++++++++ Userland/crash.cpp | 12 +++++++++++- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Base/usr/share/man/man1/crash.md b/Base/usr/share/man/man1/crash.md index be4cc175975..f85d681fb5b 100644 --- a/Base/usr/share/man/man1/crash.md +++ b/Base/usr/share/man/man1/crash.md @@ -32,6 +32,7 @@ kinds of crashes. * `-x`: Read from recently freed memory. (Tests an opportunistic malloc guard.) * `-y`: Write to recently freed memory. (Tests an opportunistic malloc guard.) * `-X`: Attempt to execute non-executable memory. (Not mapped with PROT\_EXEC.) +* `-U`: Attempt to trigger an x86 User Mode Instruction Prevention fault. ## Examples diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp index 12c05f6cc39..4eb17dc968a 100644 --- a/Kernel/Arch/i386/CPU.cpp +++ b/Kernel/Arch/i386/CPU.cpp @@ -549,6 +549,7 @@ bool g_cpu_supports_pae; bool g_cpu_supports_pge; bool g_cpu_supports_smep; bool g_cpu_supports_sse; +bool g_cpu_supports_umip; void detect_cpu_features() { @@ -562,4 +563,5 @@ void detect_cpu_features() CPUID extended_features(0x7); g_cpu_supports_smep = (extended_features.ebx() & (1 << 7)); + g_cpu_supports_umip = (extended_features.ecx() & (1 << 2)); } diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h index 9c831ad0670..9542383a2f3 100644 --- a/Kernel/Arch/i386/CPU.h +++ b/Kernel/Arch/i386/CPU.h @@ -513,3 +513,4 @@ extern bool g_cpu_supports_pae; extern bool g_cpu_supports_pge; extern bool g_cpu_supports_smep; extern bool g_cpu_supports_sse; +extern bool g_cpu_supports_umip; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index 05d3be0b894..6cb9dbe598f 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -258,6 +258,14 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables) kprintf("x86: SSE support enabled\n"); } + if (g_cpu_supports_umip) { + asm volatile( + "mov %cr4, %eax\n" + "orl $0x800, %eax\n" + "mov %eax, %cr4\n"); + kprintf("x86: UMIP support enabled\n"); + } + RTC::initialize(); PIC::initialize(); gdt_init(); diff --git a/Userland/crash.cpp b/Userland/crash.cpp index 8666fa6fb4b..19faf069c7e 100644 --- a/Userland/crash.cpp +++ b/Userland/crash.cpp @@ -10,7 +10,7 @@ static void print_usage_and_exit() { - printf("usage: crash -[AsdiamfMFTtSxyX]\n"); + printf("usage: crash -[AsdiamfMFTtSxyXU]\n"); exit(0); } @@ -98,6 +98,7 @@ int main(int argc, char** argv) WriteToFreedMemoryStillCachedByMalloc, ReadFromFreedMemoryStillCachedByMalloc, ExecuteNonExecutableMemory, + TriggerUserModeInstructionPrevention, }; Mode mode = SegmentationViolation; @@ -136,6 +137,8 @@ int main(int argc, char** argv) mode = WriteToFreedMemoryStillCachedByMalloc; else if (String(argv[1]) == "-X") mode = ExecuteNonExecutableMemory; + else if (String(argv[1]) == "-U") + mode = TriggerUserModeInstructionPrevention; else print_usage_and_exit(); @@ -320,6 +323,13 @@ int main(int argc, char** argv) }).run(run_type); } + if (mode == TriggerUserModeInstructionPrevention || mode == TestAllCrashTypes) { + Crash("Trigger x86 User Mode Instruction Prevention", []() { + asm volatile("str %eax"); + return Crash::Failure::DidNotCrash; + }).run(run_type); + } + return 0; }