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 --- arch/riscv64/kernel/entry.S | 4 +++- common/canary.c | 39 +++++++++++++++++++++++++++++++++++++++ common/tcb.c | 12 ++++++++---- common/uapi/dispatch.c | 21 +++++++++++++++++---- config.h | 3 ++- include/apos/canary.h | 27 +++++++++++++++++++++++++++ include/apos/mem.h | 20 ++++++++++---------- include/apos/types.h | 2 ++ 8 files changed, 108 insertions(+), 20 deletions(-) create mode 100644 common/canary.c create mode 100644 include/apos/canary.h diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S index 9c7a54c..7301d4e 100644 --- a/arch/riscv64/kernel/entry.S +++ b/arch/riscv64/kernel/entry.S @@ -29,7 +29,8 @@ _save_context: mv sp, tp /* move thread pointer back */ - csrrw tp, CSR_SSCRATCH, tp + addi tp, tp, sizeof_registers + csrrw tp, CSR_SSCRATCH, tp /* save registers */ sr ra, offsetof_ra(sp) @@ -77,6 +78,7 @@ _save_context: handle_exception: li t0, EXC_SYSCALL /* system exceptions fall through, syscalls jump */ + /* temp, at some point we want to handle system exceptions as well */ beq s4, t0, handle_syscall j restore_all 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; } diff --git a/config.h b/config.h index a5f9562..40899c5 100644 --- a/config.h +++ b/config.h @@ -1 +1,2 @@ -#define MAX_CPUS 16 +#define MAX_CPUS 16 +#define KERNEL_STACK_PAGE_ORDER 0 diff --git a/include/apos/canary.h b/include/apos/canary.h new file mode 100644 index 0000000..30a3dd2 --- /dev/null +++ b/include/apos/canary.h @@ -0,0 +1,27 @@ +#ifndef APOS_CANARY_H +#define APOS_CANARY_H + +/** + * @file canary.h + * Kernel stack canary handling. + */ + +#include +#include + +/** + * Place canary at end of kernel stack. + * + * @param t \ref tcb whose kernel stack to place canary in. + */ +void set_canary(struct tcb *t); + +/** + * Check that canary hasn't been accidentally overwritten. + * + * @param t \ref tcb whose kernel stack canary to check. + * @return \ref true if overwritten, \ref false otherwise. + */ +bool check_canary(struct tcb *t); + +#endif /* APOS_CANARY_H */ diff --git a/include/apos/mem.h b/include/apos/mem.h index 08aad1f..512f1e7 100644 --- a/include/apos/mem.h +++ b/include/apos/mem.h @@ -245,34 +245,34 @@ extern size_t __mm_max_order; /** Give names to page orders. */ enum mm_order { /** Base order. */ - MM_O0, + MM_O0 = 0, /** Order 1. */ - MM_O1, + MM_O1 = 1, /** Order 2. */ - MM_O2, + MM_O2 = 2, /** Order 3. */ - MM_O3, + MM_O3 = 3, /** Order 4. */ - MM_O4, + MM_O4 = 4, /** Order 5. */ - MM_O5, + MM_O5 = 5, /** Order 6. */ - MM_O6, + MM_O6 = 6, /** Order 7. */ - MM_O7, + MM_O7 = 7, /** Order 8. */ - MM_O8, + MM_O8 = 8, /** Order 9. */ - MM_O9, + MM_O9 = 9, }; /** Page number. */ diff --git a/include/apos/types.h b/include/apos/types.h index 10ad80a..f249705 100644 --- a/include/apos/types.h +++ b/include/apos/types.h @@ -455,6 +455,8 @@ typedef uint_fast16_t vmflags_t; */ /* should this enum be somewhere else? */ enum status_codes { + /** Internal error, should probably halt */ + ERR_INT = -9, /** Something went wrong :/ */ ERR_MISC = -8, /** Not initialized. */ -- cgit v1.3