Skip to content

Commit

Permalink
Kernel: Disable x86 RDTSC instruction in userspace
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
awesomekling committed Jan 1, 2020
1 parent dfd759f commit 38f93ef
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 1 deletion.
1 change: 1 addition & 0 deletions Base/usr/share/man/man1/crash.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ kinds of crashes.
* `-X`: Attempt to execute non-executable memory. (Not mapped with PROT\_EXEC.)
* `-U`: Attempt to trigger an x86 User Mode Instruction Prevention fault.
* `-I`: Use an x86 I/O instruction in userspace.
* `-c`: Read the x86 TSC (Time Stamp Counter) directly.

## Examples

Expand Down
2 changes: 2 additions & 0 deletions Kernel/Arch/i386/CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,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_tsc;
bool g_cpu_supports_umip;

void detect_cpu_features()
Expand All @@ -534,6 +535,7 @@ void detect_cpu_features()
g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
g_cpu_supports_tsc = (processor_info.edx() & (1 << 4));

CPUID extended_processor_info(0x80000001);
g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
Expand Down
1 change: 1 addition & 0 deletions Kernel/Arch/i386/CPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -513,4 +513,5 @@ 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_tsc;
extern bool g_cpu_supports_umip;
2 changes: 2 additions & 0 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2452,6 +2452,8 @@ int Process::sys$read_tsc(u32* lsw, u32* msw)
if (!validate_write_typed(msw))
return -EFAULT;
read_tsc(*lsw, *msw);
if (!is_superuser())
*lsw &= ~0xfff;
return 0;
}

Expand Down
8 changes: 8 additions & 0 deletions Kernel/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,14 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables)
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();
PIC::initialize();
gdt_init();
Expand Down
12 changes: 11 additions & 1 deletion Userland/crash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

static void print_usage_and_exit()
{
printf("usage: crash -[AsdiamfMFTtSxyXUI]\n");
printf("usage: crash -[AsdiamfMFTtSxyXUIc]\n");
exit(0);
}

Expand Down Expand Up @@ -101,6 +101,7 @@ int main(int argc, char** argv)
ExecuteNonExecutableMemory,
TriggerUserModeInstructionPrevention,
UseIOInstruction,
ReadTimestampCounter,
};
Mode mode = SegmentationViolation;

Expand Down Expand Up @@ -143,6 +144,8 @@ int main(int argc, char** argv)
mode = TriggerUserModeInstructionPrevention;
else if (String(argv[1]) == "-I")
mode = UseIOInstruction;
else if (String(argv[1]) == "-c")
mode = ReadTimestampCounter;
else
print_usage_and_exit();

Expand Down Expand Up @@ -342,5 +345,12 @@ int main(int argc, char** argv)
}).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;
}

0 comments on commit 38f93ef

Please sign in to comment.