Browse Source

Kernel: Disable x86 RDTSC instruction in userspace

It's still possible to read the TSC via the read_tsc() syscall, but we
will now clear some of the bottom bits for unprivileged users.
Andreas Kling 5 years ago
parent
commit
38f93ef13b

+ 1 - 0
Base/usr/share/man/man1/crash.md

@@ -34,6 +34,7 @@ kinds of crashes.
 * `-X`: Attempt to execute non-executable memory. (Not mapped with PROT\_EXEC.)
 * `-X`: Attempt to execute non-executable memory. (Not mapped with PROT\_EXEC.)
 * `-U`: Attempt to trigger an x86 User Mode Instruction Prevention fault.
 * `-U`: Attempt to trigger an x86 User Mode Instruction Prevention fault.
 * `-I`: Use an x86 I/O instruction in userspace.
 * `-I`: Use an x86 I/O instruction in userspace.
+* `-c`: Read the x86 TSC (Time Stamp Counter) directly.
 
 
 ## Examples
 ## Examples
 
 

+ 2 - 0
Kernel/Arch/i386/CPU.cpp

@@ -526,6 +526,7 @@ bool g_cpu_supports_pae;
 bool g_cpu_supports_pge;
 bool g_cpu_supports_pge;
 bool g_cpu_supports_smep;
 bool g_cpu_supports_smep;
 bool g_cpu_supports_sse;
 bool g_cpu_supports_sse;
+bool g_cpu_supports_tsc;
 bool g_cpu_supports_umip;
 bool g_cpu_supports_umip;
 
 
 void detect_cpu_features()
 void detect_cpu_features()
@@ -534,6 +535,7 @@ void detect_cpu_features()
     g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
     g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
     g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
     g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
     g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
     g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
+    g_cpu_supports_tsc = (processor_info.edx() & (1 << 4));
 
 
     CPUID extended_processor_info(0x80000001);
     CPUID extended_processor_info(0x80000001);
     g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
     g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));

+ 1 - 0
Kernel/Arch/i386/CPU.h

@@ -513,4 +513,5 @@ extern bool g_cpu_supports_pae;
 extern bool g_cpu_supports_pge;
 extern bool g_cpu_supports_pge;
 extern bool g_cpu_supports_smep;
 extern bool g_cpu_supports_smep;
 extern bool g_cpu_supports_sse;
 extern bool g_cpu_supports_sse;
+extern bool g_cpu_supports_tsc;
 extern bool g_cpu_supports_umip;
 extern bool g_cpu_supports_umip;

+ 2 - 0
Kernel/Process.cpp

@@ -2452,6 +2452,8 @@ int Process::sys$read_tsc(u32* lsw, u32* msw)
     if (!validate_write_typed(msw))
     if (!validate_write_typed(msw))
         return -EFAULT;
         return -EFAULT;
     read_tsc(*lsw, *msw);
     read_tsc(*lsw, *msw);
+    if (!is_superuser())
+        *lsw &= ~0xfff;
     return 0;
     return 0;
 }
 }
 
 

+ 8 - 0
Kernel/init.cpp

@@ -266,6 +266,14 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables)
         kprintf("x86: UMIP support enabled\n");
         kprintf("x86: UMIP support enabled\n");
     }
     }
 
 
+    if (g_cpu_supports_tsc) {
+        asm volatile(
+            "mov %cr4, %eax\n"
+            "orl $0x4, %eax\n"
+            "mov %eax, %cr4\n");
+        kprintf("x86: RDTSC support restricted\n");
+    }
+
     RTC::initialize();
     RTC::initialize();
     PIC::initialize();
     PIC::initialize();
     gdt_init();
     gdt_init();

+ 11 - 1
Userland/crash.cpp

@@ -11,7 +11,7 @@
 
 
 static void print_usage_and_exit()
 static void print_usage_and_exit()
 {
 {
-    printf("usage: crash -[AsdiamfMFTtSxyXUI]\n");
+    printf("usage: crash -[AsdiamfMFTtSxyXUIc]\n");
     exit(0);
     exit(0);
 }
 }
 
 
@@ -101,6 +101,7 @@ int main(int argc, char** argv)
         ExecuteNonExecutableMemory,
         ExecuteNonExecutableMemory,
         TriggerUserModeInstructionPrevention,
         TriggerUserModeInstructionPrevention,
         UseIOInstruction,
         UseIOInstruction,
+        ReadTimestampCounter,
     };
     };
     Mode mode = SegmentationViolation;
     Mode mode = SegmentationViolation;
 
 
@@ -143,6 +144,8 @@ int main(int argc, char** argv)
         mode = TriggerUserModeInstructionPrevention;
         mode = TriggerUserModeInstructionPrevention;
     else if (String(argv[1]) == "-I")
     else if (String(argv[1]) == "-I")
         mode = UseIOInstruction;
         mode = UseIOInstruction;
+    else if (String(argv[1]) == "-c")
+        mode = ReadTimestampCounter;
     else
     else
         print_usage_and_exit();
         print_usage_and_exit();
 
 
@@ -342,5 +345,12 @@ int main(int argc, char** argv)
         }).run(run_type);
         }).run(run_type);
     }
     }
 
 
+    if (mode == ReadTimestampCounter || mode == TestAllCrashTypes) {
+        Crash("Read the CPU timestamp counter", [] {
+            asm volatile("rdtsc");
+            return Crash::Failure::DidNotCrash;
+        }).run(run_type);
+    }
+
     return 0;
     return 0;
 }
 }