From 227cf5c03e99c8c3d0092f5dda47d31c63afd896 Mon Sep 17 00:00:00 2001 From: cozis Date: Tue, 2 Jun 2026 12:10:19 +0200 Subject: [PATCH] scheduler: Add canary bytes to detect stack overflows --- src/scheduler.zig | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/scheduler.zig b/src/scheduler.zig index f45f06c..56340fb 100644 --- a/src/scheduler.zig +++ b/src/scheduler.zig @@ -17,6 +17,9 @@ const ContextSwitch = extern struct { new: *Registers, }; +const STACK_CANARY_SIZE = 256; +const STACK_CANARY_BYTE = 0xa5; + const State = enum { ready, running, @@ -32,6 +35,15 @@ const Task = struct { state : State, wakeup: ?u64, 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, @@ -56,8 +68,12 @@ pub fn deinit(self: *Scheduler) 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); + @memset(stack[0..STACK_CANARY_SIZE], STACK_CANARY_BYTE); var stack_top = @intFromPtr(stack.ptr) + stack.len; stack_top &= ~@as(usize, 0xf); @@ -127,6 +143,8 @@ pub fn scheduleOne(self: *Scheduler) bool { self.current = task; task.state = .running; contextSwitch(&self.regs, &task.regs); + if (!task.stackCanaryIsIntact()) + @panic("Task stack canary was overwritten"); return true; }