From df62e54d1e49cbcf06c88b6be79ed6b174e901ac Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Thu, 13 Aug 2020 15:05:08 -0400 Subject: [PATCH] Kernel: Request random numbers for syscall stack noise in larger chunks (#3125) Cuts time needed for `disasm /bin/id` from 2.5s to 1s -- identical to the time it needs when not doing the random adjustment at all. The downside is that it's now very easy to get the random offsets with out-of-bounds reads, so it does make this mitigation less effective. --- Kernel/Syscall.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index 97d7fc5013..0d78c75025 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -120,6 +120,10 @@ int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3) } +constexpr int RandomByteBufferSize = 256; +u8 g_random_byte_buffer[RandomByteBufferSize]; +int g_random_byte_buffer_offset = RandomByteBufferSize; + void syscall_handler(TrapFrame* trap) { auto& regs = *trap->regs; @@ -135,7 +139,13 @@ void syscall_handler(TrapFrame* trap) // Apply a random offset in the range 0-255 to the stack pointer, // to make kernel stacks a bit less deterministic. - auto* ptr = (char*)__builtin_alloca(get_fast_random()); + // Since this is very hot code, request random data in chunks instead of + // one byte at a time. This is a noticeable speedup. + if (g_random_byte_buffer_offset == RandomByteBufferSize) { + get_fast_random_bytes(g_random_byte_buffer, RandomByteBufferSize); + g_random_byte_buffer_offset = 0; + } + auto* ptr = (char*)__builtin_alloca(g_random_byte_buffer[g_random_byte_buffer_offset++]); asm volatile("" : "=m"(*ptr));