aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-09-05 11:18:38 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-09-05 11:21:18 +0200
commit3eb72bb6bc7446df3e34bd990cb84a0b8178b9cd (patch)
tree21a8c11f4d140c5babe921efa2b9acfb125df1b3 /arch
parent3697f01a3906815cbbbe8927f50045163976c1db (diff)
downloadkernel-3eb72bb6bc7446df3e34bd990cb84a0b8178b9cd.tar.xz
kernel-3eb72bb6bc7446df3e34bd990cb84a0b8178b9cd.zip
x86_64/cpu: improve stack overflow detection
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/arch/cpu/interrupts.cpp29
-rw-r--r--arch/x86_64/scripts/kernel.ld2
2 files changed, 29 insertions, 2 deletions
diff --git a/arch/x86_64/arch/cpu/interrupts.cpp b/arch/x86_64/arch/cpu/interrupts.cpp
index 94806621..f27c3a2e 100644
--- a/arch/x86_64/arch/cpu/interrupts.cpp
+++ b/arch/x86_64/arch/cpu/interrupts.cpp
@@ -9,7 +9,9 @@
#include <kapi/system.hpp>
#include <kstd/print.hpp>
+#include <kstd/units.hpp>
+#include <cstddef>
#include <cstdint>
namespace arch::cpu
@@ -17,6 +19,9 @@ namespace arch::cpu
namespace
{
+ extern "C" std::byte __kernel_stack_bottom[]; // NOLINT(readability-identifier-naming)
+ extern "C" std::byte __ist1_stack_bottom[]; // NOLINT(readability-identifier-naming)
+
enum struct exception
{
divide_error,
@@ -128,8 +133,28 @@ namespace arch::cpu
auto handle_double_fault(interrupt_frame * frame) -> void
{
- kapi::system::panic("[ARCH:CPU] Double fault! Possible kernel stack corruption! rsp was {}",
- frame->cpu_saved.rsp);
+ auto const rsp = frame->cpu_saved.rsp;
+ auto const rip = frame->cpu_saved.rip;
+ auto const kernel_stack_bottom = kapi::memory::linear_address{__kernel_stack_bottom};
+ auto const ist1_stack_bottom = kapi::memory::linear_address{__ist1_stack_bottom};
+
+ auto const overflowed_kernel = rsp < kernel_stack_bottom && rsp >= kernel_stack_bottom - kapi::memory::page::size;
+ auto const overflowed_ist1 = rsp < ist1_stack_bottom && rsp >= ist1_stack_bottom - kapi::memory::page::size;
+
+ if (overflowed_kernel || overflowed_ist1)
+ {
+ auto const overflowed_what = overflowed_kernel ? "kernel" : "ist1";
+ auto const overflowed_by =
+ kstd::bytes{static_cast<std::size_t>((overflowed_kernel ? kernel_stack_bottom : ist1_stack_bottom) - rsp)};
+
+ kapi::system::panic("[ARCH:CPU] Suspected {} stack overflow: \n" //
+ "\toverflowed by: {:#}\n" //
+ "\trsp: {}\n" //
+ "\trip: {}\n", //
+ overflowed_what, overflowed_by, rsp, rip);
+ }
+
+ kapi::system::panic("[ARCH:CPU] Double fault at {}", rip);
}
} // namespace
diff --git a/arch/x86_64/scripts/kernel.ld b/arch/x86_64/scripts/kernel.ld
index 8cd6c1c3..f96152d7 100644
--- a/arch/x86_64/scripts/kernel.ld
+++ b/arch/x86_64/scripts/kernel.ld
@@ -100,6 +100,7 @@ SECTIONS
.kernel_stack ALIGN(4K) : AT (ADDR (.kernel_stack) - TEACHOS_VMA)
{
+ PROVIDE_HIDDEN(__kernel_stack_bottom = .);
*(.stack)
} :kernel_data
@@ -107,6 +108,7 @@ SECTIONS
.kernel_ist1_stack ALIGN(4K) : AT (ADDR (.kernel_ist1_stack) - TEACHOS_VMA)
{
+ PROVIDE_HIDDEN(__ist1_stack_bottom = .);
*(.ist1_stack)
} :kernel_data