From cabbf335824db0df835e4c541c19d3803ce38454 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 14 Sep 2022 21:30:11 +0300 Subject: add canary to kernel stack --- common/canary.c | 39 +++++++++++++++++++++++++++++++++++++++ common/tcb.c | 12 ++++++++---- common/uapi/dispatch.c | 21 +++++++++++++++++---- 3 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 common/canary.c (limited to 'common') diff --git a/common/canary.c b/common/canary.c new file mode 100644 index 0000000..9fd89ff --- /dev/null +++ b/common/canary.c @@ -0,0 +1,39 @@ +#include +#include + +/** + * @file canary.c + * Kernel stack canary implementation. + */ + +/** Typedef for canary value type. */ +typedef uint32_t canary_t; + +/** Canary magic value. */ +static const canary_t canary = 0xb00b1e5; + +/** + * Helper for calculating the canary location of \p t. + * + * @param t \ref tcb to calculate canary position of. + * @return Pointer to canary location, that is bottom of stack. + * \todo This assumes that all stacks grow downwards. Unlikely to ever be + * ported to a platform that doesn't abide by this, but keep it in mind anyway. + */ +static canary_t *get_canary(struct tcb *t) +{ + size_t s = order_size(KERNEL_STACK_PAGE_ORDER); + return (canary_t *)align_down((uintptr_t)t, s); +} + +void set_canary(struct tcb *t) +{ + canary_t *c = get_canary(t); + *c = canary; +} + +bool check_canary(struct tcb *t) +{ + canary_t *c = get_canary(t); + return *c != canary; +} diff --git a/common/tcb.c b/common/tcb.c index 1e25f47..9768eb0 100644 --- a/common/tcb.c +++ b/common/tcb.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -16,6 +15,9 @@ #include #include #include +#include + +#include #include /* arguably exessively many globals... */ @@ -137,7 +139,7 @@ struct tcb *create_thread(struct tcb *p) { hard_assert(tcbs, 0); - vm_t bottom = alloc_page(MM_O0, 0); + vm_t bottom = alloc_page(KERNEL_STACK_PAGE_ORDER, 0); /* move tcb to top of kernel stack, keeping alignment in check * (hopefully) */ /** \todo check alignment */ @@ -163,6 +165,7 @@ struct tcb *create_thread(struct tcb *p) t->rid = p->rid; t->rpc.vmem = create_vmem(); + set_canary(t); return t; } @@ -303,8 +306,9 @@ struct tcb *cur_proc() void use_tcb(struct tcb *t) { - t->cpu_id = cpu_id(); - cpu_tcb[cpu_id()] = t; + id_t cpu = cpu_id(); + t->cpu_id = cpu; + cpu_tcb[cpu] = t; } struct tcb *get_tcb(id_t tid) diff --git a/common/uapi/dispatch.c b/common/uapi/dispatch.c index c2ddbcf..73e037a 100644 --- a/common/uapi/dispatch.c +++ b/common/uapi/dispatch.c @@ -6,6 +6,7 @@ * Syscall dispatch. */ +#include #include #include @@ -57,11 +58,23 @@ SYSCALL_DEFINE0(noop)(){ struct sys_ret syscall_dispatch(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, sys_arg_t c, sys_arg_t d) { - /** \todo Add check that syscall is not larger than table */ - sys_t call = syscall_table[syscall]; + struct tcb *t = cur_tcb(); - if (!call) + size_t sc = syscall; + if (sc >= ARRAY_SIZE(syscall_table)) { + error("Syscall %zu outside allowed range [0 - %zu]\n", sc, + ARRAY_SIZE(syscall_table)); return (struct sys_ret){ ERR_INVAL, 0 }; + } - return call(a, b, c, d); + /* the syscall must be a valid number, as they're numbered in a linear + * fashion */ + struct sys_ret r = syscall_table[syscall](a, b, c, d); + + if (check_canary(t)) { + bug("Syscall %zu overwrote stack canary\n", syscall); + return (struct sys_ret){ ERR_INT, 0 }; + } + + return r; } -- cgit v1.3