Skip to content

Commit 3a3de1c

Browse files
authored
Merge pull request #46 from sysprog21/stack-canary
Replace constant stack canary with per-task random
2 parents bb01758 + 4a8087c commit 3a3de1c

File tree

3 files changed

+23
-10
lines changed

3 files changed

+23
-10
lines changed

include/sys/task.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ typedef struct tcb {
8282

8383
/* Real-time Scheduling Support */
8484
void *rt_prio; /* Opaque pointer for custom real-time scheduler hook */
85+
86+
/* Stack Protection */
87+
uint32_t canary; /* Random stack canary for overflow detection */
8588
} tcb_t;
8689

8790
/* Kernel Control Block (KCB)

kernel/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ int32_t main(void)
2424
printf("Heap initialized, %u bytes available\n",
2525
(unsigned int) (size_t) &_heap_size);
2626

27+
/* Seed PRNG with hardware entropy for stack canary randomization.
28+
* Combine cycle counter (mcycle) and us timer for unpredictability. This
29+
* prevents fixed canary values across boots.
30+
*/
31+
uint32_t entropy = read_csr(mcycle) ^ (uint32_t) _read_us();
32+
srand(entropy);
33+
2734
/* Initialize deferred logging system.
2835
* Must be done after heap init but before app_main() to ensure
2936
* application tasks can use thread-safe printf.

kernel/task.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include <hal.h>
9+
#include <lib/libc.h>
910
#include <lib/queue.h>
1011
#include <sys/task.h>
1112

@@ -41,10 +42,6 @@ static volatile uint32_t timer_work_generation = 0; /* counter for coalescing */
4142
/* Stack canary checking frequency - check every N context switches */
4243
#define STACK_CHECK_INTERVAL 32
4344

44-
/* Magic number written to both ends of a task's stack for corruption detection.
45-
*/
46-
#define STACK_CANARY 0x33333333U
47-
4845
/* Stack check counter for periodic validation (reduces overhead). */
4946
static uint32_t stack_check_counter = 0;
5047
#endif /* CONFIG_STACK_PROTECTION */
@@ -153,12 +150,12 @@ static void task_stack_check(void)
153150
uint32_t *hi_canary_ptr = (uint32_t *) ((uintptr_t) self->stack +
154151
self->stack_sz - sizeof(uint32_t));
155152

156-
if (unlikely(*lo_canary_ptr != STACK_CANARY ||
157-
*hi_canary_ptr != STACK_CANARY)) {
153+
if (unlikely(*lo_canary_ptr != self->canary ||
154+
*hi_canary_ptr != self->canary)) {
158155
printf("\n*** STACK CORRUPTION: task %u base=%p size=%u\n", self->id,
159156
self->stack, (unsigned int) self->stack_sz);
160157
printf(" Canary values: low=0x%08x, high=0x%08x (expected 0x%08x)\n",
161-
*lo_canary_ptr, *hi_canary_ptr, STACK_CANARY);
158+
*lo_canary_ptr, *hi_canary_ptr, self->canary);
162159
panic(ERR_STACK_CHECK);
163160
}
164161
}
@@ -544,10 +541,16 @@ static bool init_task_stack(tcb_t *tcb, size_t stack_size)
544541
}
545542

546543
#if CONFIG_STACK_PROTECTION
547-
/* Only initialize essential parts to reduce overhead */
548-
*(uint32_t *) stack = STACK_CANARY;
544+
/* Generate random canary for this task */
545+
tcb->canary = (uint32_t) random();
546+
/* Ensure canary is never zero */
547+
if (tcb->canary == 0)
548+
tcb->canary = 0xDEADBEEFU;
549+
550+
/* Write canary to both ends of stack */
551+
*(uint32_t *) stack = tcb->canary;
549552
*(uint32_t *) ((uintptr_t) stack + stack_size - sizeof(uint32_t)) =
550-
STACK_CANARY;
553+
tcb->canary;
551554
#endif
552555

553556
tcb->stack = stack;

0 commit comments

Comments
 (0)