aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/riscv64/kernel/entry.S4
-rw-r--r--common/canary.c39
-rw-r--r--common/tcb.c12
-rw-r--r--common/uapi/dispatch.c21
-rw-r--r--config.h3
-rw-r--r--include/apos/canary.h27
-rw-r--r--include/apos/mem.h20
-rw-r--r--include/apos/types.h2
8 files changed, 108 insertions, 20 deletions
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 <apos/canary.h>
+#include <apos/mem.h>
+
+/**
+ * @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 <apos/tcb.h>
-#include <arch/cpu.h>
#include <apos/mem.h>
#include <apos/conf.h>
#include <apos/pmem.h>
@@ -16,6 +15,9 @@
#include <apos/types.h>
#include <apos/assert.h>
#include <apos/string.h>
+#include <apos/canary.h>
+
+#include <arch/cpu.h>
#include <arch/vmem.h>
/* 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 <apos/canary.h>
#include <apos/debug.h>
#include <apos/uapi.h>
@@ -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 <apos/tcb.h>
+#include <apos/types.h>
+
+/**
+ * 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. */