altos: Add AO_STACK_CANARY to detect stack overflows sometimes
authorKeith Packard <keithp@keithp.com>
Tue, 13 Jun 2023 06:13:29 +0000 (23:13 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 13 Jun 2023 06:18:21 +0000 (23:18 -0700)
Checks above and below the current task stack at each switch.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/kernel/ao_task.c
src/kernel/ao_task.h

index b50454167b67d70fdcea806f75ac3a21afb74b9d..048f5e67c6e39b58c4c0d5c633a9d77028297c10 100644 (file)
@@ -307,6 +307,8 @@ ao_stack_top(struct ao_task *task)
 #endif
 }
 
+#define AO_STACK_CANARY_VALUE  0xbaadf00dU
+
 void
 ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name) 
 {
@@ -324,6 +326,10 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name)
        task->task_id = task_id;
        task->name = name;
        task->wchan = NULL;
+#ifdef AO_STACK_CANARY
+       task->bottom_canary = AO_STACK_CANARY_VALUE;
+       task->top_canary = AO_STACK_CANARY_VALUE;
+#endif
        /*
         * Construct a stack frame so that it will 'return'
         * to the start of the task
@@ -341,6 +347,19 @@ ao_add_task(struct ao_task * task, void (*task_func)(void), const char *name)
                );
 }
 
+#ifdef AO_STACK_CANARY
+static void
+ao_check_stack_canary(void)
+{
+       if (ao_cur_task->bottom_canary != AO_STACK_CANARY_VALUE)
+               ao_panic(AO_PANIC_STACK);
+       if (ao_cur_task->top_canary != AO_STACK_CANARY_VALUE)
+               ao_panic(AO_PANIC_STACK);
+}
+#else
+#define ao_check_stack_canary()
+#endif
+
 uint8_t        ao_task_minimize_latency;
 
 /* Task switching function. */
@@ -356,6 +375,7 @@ ao_yield(void)
                        ao_cur_task->max_run = run;
                ++ao_cur_task->yields;
 #endif
+               ao_check_stack_canary();
                ao_arch_save_regs();
                ao_arch_save_stack();
        }
@@ -398,6 +418,7 @@ ao_yield(void)
 #if USE_TLS
        _set_tls(ao_stack_top(ao_cur_task));
 #endif
+       ao_check_stack_canary();
        ao_arch_restore_stack();
 }
 
index 9197e25cef0f6f1c828d033404227206cd75a934..27f47a5629de139565d203e34f3c63ccc21998e3 100644 (file)
@@ -48,10 +48,16 @@ struct ao_task {
        struct ao_list  queue;
        struct ao_list  alarm_queue;
        /* Provide both 32-bit and 8-bit stacks */
+#ifdef AO_STACK_CANARY
+       uint32_t        bottom_canary;
+#endif
        union {
                uint32_t stack32[AO_STACK_SIZE>>2];
                uint8_t stack8[AO_STACK_SIZE];
        } AO_STACK_ALIGNMENT;
+#ifdef AO_STACK_CANARY
+       uint32_t top_canary;
+#endif
 #if HAS_SAMPLE_PROFILE
        uint32_t ticks;
        uint32_t yields;