scheduler: Add canary bytes to detect stack overflows

This commit is contained in:
2026-06-02 12:10:19 +02:00
parent c922ed62e1
commit 227cf5c03e
+19 -1
View File
@@ -17,6 +17,9 @@ const ContextSwitch = extern struct {
new: *Registers, new: *Registers,
}; };
const STACK_CANARY_SIZE = 256;
const STACK_CANARY_BYTE = 0xa5;
const State = enum { const State = enum {
ready, ready,
running, running,
@@ -32,6 +35,15 @@ const Task = struct {
state : State, state : State,
wakeup: ?u64, wakeup: ?u64,
node : *Node, node : *Node,
fn stackCanaryIsIntact(self: *Task) bool {
const canary = self.stack[0..STACK_CANARY_SIZE];
for (canary) |byte| {
if (byte != STACK_CANARY_BYTE)
return false;
}
return true;
}
}; };
gpa: Allocator, gpa: Allocator,
@@ -56,8 +68,12 @@ pub fn deinit(self: *Scheduler) void {
pub fn spawn(self: *Scheduler, node: *Node, entry: EntryPoint, stack_size: usize) !void { pub fn spawn(self: *Scheduler, node: *Node, entry: EntryPoint, stack_size: usize) !void {
const stack = try std.heap.page_allocator.alignedAlloc(u8, .fromByteUnits(16), stack_size); if (stack_size > std.math.maxInt(usize) - STACK_CANARY_SIZE)
return Allocator.Error.OutOfMemory;
const stack = try std.heap.page_allocator.alignedAlloc(u8, .fromByteUnits(16), stack_size + STACK_CANARY_SIZE);
errdefer std.heap.page_allocator.free(stack); errdefer std.heap.page_allocator.free(stack);
@memset(stack[0..STACK_CANARY_SIZE], STACK_CANARY_BYTE);
var stack_top = @intFromPtr(stack.ptr) + stack.len; var stack_top = @intFromPtr(stack.ptr) + stack.len;
stack_top &= ~@as(usize, 0xf); stack_top &= ~@as(usize, 0xf);
@@ -127,6 +143,8 @@ pub fn scheduleOne(self: *Scheduler) bool {
self.current = task; self.current = task;
task.state = .running; task.state = .running;
contextSwitch(&self.regs, &task.regs); contextSwitch(&self.regs, &task.regs);
if (!task.stackCanaryIsIntact())
@panic("Task stack canary was overwritten");
return true; return true;
} }