From efb28d3258d770b5d0c11cb56ce153721e7880cb Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 14 Sep 2022 18:54:40 +0200 Subject: [PATCH] Randomness and stack protection!! --- kernel/Makefile | 10 +++++- kernel/include/assert.h | 4 ++- kernel/include/rand/Init.h | 7 ++++ kernel/include/rand/Mersenne.h | 8 +++++ kernel/src/init/Init.cpp | 8 +++++ kernel/src/interrupts/IRQ.cpp | 2 ++ kernel/src/main.cpp | 1 + kernel/src/rand/Init.asm | 10 ++++++ kernel/src/rand/Init.cpp | 66 ++++++++++++++++++++++++++++++++++ kernel/src/rand/Mersenne.cpp | 62 ++++++++++++++++++++++++++++++++ kernel/src/stack.cpp | 7 ++++ 11 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 kernel/include/rand/Init.h create mode 100644 kernel/include/rand/Mersenne.h create mode 100644 kernel/src/rand/Init.asm create mode 100644 kernel/src/rand/Init.cpp create mode 100644 kernel/src/rand/Mersenne.cpp create mode 100644 kernel/src/stack.cpp diff --git a/kernel/Makefile b/kernel/Makefile index baa6f8d1..1478195d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -8,7 +8,7 @@ CXX := x86_64-elf-g++ AS := x86_64-elf-as NASM := nasm -CFLAGS := -Wall -Wextra -Werror -Os -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std +CFLAGS := -Wall -Wextra -Werror -Os -ffreestanding -fstack-protector-all -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std CXXFLAGS := -fno-rtti -fno-exceptions NASMFLAGS := -felf64 ASFLAGS := @@ -40,6 +40,14 @@ $(MOON_OBJ)/interrupts/handlers.cpp.o: $(MOON_SRC)/interrupts/handlers.cpp @mkdir -p $(@D) $(CXX) $(CFLAGS) -mgeneral-regs-only $(CXXFLAGS) -o $@ -c $^ +$(MOON_OBJ)/main.cpp.o: $(MOON_SRC)/main.cpp + @mkdir -p $(@D) + $(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^ + +$(MOON_OBJ)/init/Init.cpp.o: $(MOON_SRC)/init/Init.cpp + @mkdir -p $(@D) + $(CXX) $(CFLAGS) -fno-stack-protector $(CXXFLAGS) -o $@ -c $^ + $(MOON_OBJ)/%.cpp.o: $(MOON_SRC)/%.cpp @mkdir -p $(@D) $(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $^ diff --git a/kernel/include/assert.h b/kernel/include/assert.h index 04701929..ca9fb709 100644 --- a/kernel/include/assert.h +++ b/kernel/include/assert.h @@ -11,4 +11,6 @@ if (!(expr)) { __call_assert_fail("Assertion failed at %s, line %d: %s", __FILE__, __LINE__, #expr) } \ } while (0) -#define TODO(message) __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message) \ No newline at end of file +#define TODO(message) __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message) + +#define PANIC(message) __call_assert_fail("PANIC at %s, line %d: %s", __FILE__, __LINE__, message) \ No newline at end of file diff --git a/kernel/include/rand/Init.h b/kernel/include/rand/Init.h new file mode 100644 index 00000000..d0b91c70 --- /dev/null +++ b/kernel/include/rand/Init.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Mersenne +{ + void init(); + void reseed(); +} \ No newline at end of file diff --git a/kernel/include/rand/Mersenne.h b/kernel/include/rand/Mersenne.h new file mode 100644 index 00000000..791b4500 --- /dev/null +++ b/kernel/include/rand/Mersenne.h @@ -0,0 +1,8 @@ +#pragma once +#include + +namespace Mersenne +{ + void seed(uint64_t); + uint64_t get(); +} \ No newline at end of file diff --git a/kernel/src/init/Init.cpp b/kernel/src/init/Init.cpp index e870f571..4bb9b343 100644 --- a/kernel/src/init/Init.cpp +++ b/kernel/src/init/Init.cpp @@ -7,12 +7,16 @@ #include "memory/RangeAllocator.h" #include "memory/VMM.h" #include "panic/hang.h" +#include "rand/Init.h" +#include "rand/Mersenne.h" #include "render/Framebuffer.h" #include "render/TextRenderer.h" #include extern BOOTBOOT bootboot; +uintptr_t __stack_chk_guard = 0xfeff34; + void Init::check_magic() { ASSERT(strncmp((char*)bootboot.magic, BOOTBOOT_MAGIC, 4) == 0); @@ -35,4 +39,8 @@ void Init::early_init() kernelPMM.init_from_mmap(); kernelVMM.init(); + + Mersenne::init(); + + __stack_chk_guard = Mersenne::get(); } \ No newline at end of file diff --git a/kernel/src/interrupts/IRQ.cpp b/kernel/src/interrupts/IRQ.cpp index e80a7ac9..b356aa44 100644 --- a/kernel/src/interrupts/IRQ.cpp +++ b/kernel/src/interrupts/IRQ.cpp @@ -1,6 +1,7 @@ #include "interrupts/IRQ.h" #include "io/IO.h" #include "io/PIC.h" +#include "rand/Init.h" #include "scheduling/PIT.h" #include "std/stdio.h" @@ -16,6 +17,7 @@ void IRQ::interrupt_handler(SavedContext* context) } default: printf("Unhandled IRQ: %ld", context->irq_number); break; } + Mersenne::reseed(); PIC::send_eoi(context->irq_number); return; } \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index fbf531d8..2ef56dd0 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -18,6 +18,7 @@ #include "memory/RangeAllocator.h" #include "panic/hang.h" #include "power/reboot.h" +#include "rand/Mersenne.h" #include "render/Framebuffer.h" #include "render/TextRenderer.h" #include "scheduling/PIT.h" diff --git a/kernel/src/rand/Init.asm b/kernel/src/rand/Init.asm new file mode 100644 index 00000000..54449791 --- /dev/null +++ b/kernel/src/rand/Init.asm @@ -0,0 +1,10 @@ +global _test_rdseed + +_test_rdseed: + mov eax, 7 + mov ecx, 0 + cpuid + shr ebx, 18 + and ebx, 1 + mov eax, ebx + ret \ No newline at end of file diff --git a/kernel/src/rand/Init.cpp b/kernel/src/rand/Init.cpp new file mode 100644 index 00000000..a1db3790 --- /dev/null +++ b/kernel/src/rand/Init.cpp @@ -0,0 +1,66 @@ +#define MODULE "rand" + +#include "rand/Init.h" +#include "config.h" +#include "cpu/CPU.h" +#include "io/IO.h" +#include "log/Log.h" +#include "rand/Mersenne.h" + +static uint64_t state = 0xf5026f5ae96319e9; + +extern "C" int _test_rdseed(); + +static uint64_t rdtsc() +{ + uint64_t result1; + uint64_t result2; + asm volatile("rdtsc" : "=a"(result1), "=d"(result2)); + return result2 << 32 | result1; +} + +static uint64_t rdseed() +{ + uint64_t result; + asm volatile("rdseed %0" : "=r"(result)); + return result; +} + +static uint64_t rdrand() +{ + uint64_t result; + asm volatile("rdrand %0" : "=r"(result)); + return result; +} + +void Mersenne::init() +{ + state ^= (0x45fe1024UL + MOON_MAJOR) * (MOON_MINOR ^ 200UL); + + state ^= 0xe0e4f5332ea75b; + + reseed(); + + state ^= Mersenne::get() * 0xffe3; + + state ^= rdtsc(); + + Mersenne::seed(state); +} + +void Mersenne::reseed() +{ + state ^= rdtsc(); + + if (CPU::has_feature(CPU::Features::RDRAND)) { state ^= rdrand(); } + + if (_test_rdseed()) { state ^= rdseed(); } + + state ^= rdtsc(); + + state ^= IO::inb(0x40); + + state ^= rdtsc(); + + Mersenne::seed(state); +} \ No newline at end of file diff --git a/kernel/src/rand/Mersenne.cpp b/kernel/src/rand/Mersenne.cpp new file mode 100644 index 00000000..fa3044b7 --- /dev/null +++ b/kernel/src/rand/Mersenne.cpp @@ -0,0 +1,62 @@ +#define MODULE "rand" + +#include "rand/Mersenne.h" +#include "assert.h" +#include + +typedef uint64_t word_t; + +static const int STATE_SIZE = 312; +static const int MIDDLE = 156; +static const int INIT_SHIFT = 62; +static const uint64_t TWIST_MASK = 0xb5026f5aa96619e9; +static const uint64_t INIT_FACT = 6364136223846793005; +static const int SHIFT1 = 29; +static const uint64_t MASK1 = 0x5555555555555555; +static const int SHIFT2 = 17; +static const uint64_t MASK2 = 0x71d67fffeda60000; +static const int SHIFT3 = 37; +static const uint64_t MASK3 = 0xfff7eee000000000; +static const int SHIFT4 = 43; + +static const word_t LOWER_MASK = 0x7fffffff; +static const word_t UPPER_MASK = (~(word_t)LOWER_MASK); + +static word_t state[STATE_SIZE]; +static size_t index = STATE_SIZE + 1; + +void Mersenne::seed(uint64_t s) +{ + index = STATE_SIZE; + state[0] = s; + for (size_t i = 1; i < STATE_SIZE; i++) state[i] = (INIT_FACT * (state[i - 1] ^ (state[i - 1] >> INIT_SHIFT))) + i; +} + +static void twist() +{ + for (size_t i = 0; i < STATE_SIZE; i++) + { + word_t x = (state[i] & UPPER_MASK) | (state[(i + 1) % STATE_SIZE] & LOWER_MASK); + x = (x >> 1) ^ (x & 1 ? TWIST_MASK : 0); + state[i] = state[(i + MIDDLE) % STATE_SIZE] ^ x; + } + index = 0; +} + +uint64_t Mersenne::get() +{ + if (index >= STATE_SIZE) + { + ASSERT(index == STATE_SIZE && "Mersenne generator was never seeded"); + twist(); + } + + word_t y = state[index]; + y ^= (y >> SHIFT1) & MASK1; + y ^= (y << SHIFT2) & MASK2; + y ^= (y << SHIFT3) & MASK3; + y ^= y >> SHIFT4; + + index++; + return y; +} \ No newline at end of file diff --git a/kernel/src/stack.cpp b/kernel/src/stack.cpp new file mode 100644 index 00000000..dc3c8c9b --- /dev/null +++ b/kernel/src/stack.cpp @@ -0,0 +1,7 @@ +#include "assert.h" +#include + +extern "C" void __stack_chk_fail() +{ + PANIC("Stack smashing detected"); +} \ No newline at end of file