diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-10-30 13:34:18 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-11-01 10:27:36 +0200 |
| commit | f139fff6ae7063c1965fa3085bb2585d7d838d72 (patch) | |
| tree | 7ee9f7c6a1ee09dba93c086cd66861474b821c97 /arch | |
| parent | b576c1d477bf476f277d32ecf60c312e4a97490d (diff) | |
| download | kmi-f139fff6ae7063c1965fa3085bb2585d7d838d72.tar.gz kmi-f139fff6ae7063c1965fa3085bb2585d7d838d72.zip | |
rpc actually marks and unmarks stack regions
+ Processes won't be able to read previous stack frames etc
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/riscv64/kernel/entry.S | 4 | ||||
| -rw-r--r-- | arch/riscv64/kernel/except.c | 1 | ||||
| -rw-r--r-- | arch/riscv64/kernel/proc.c | 3 | ||||
| -rw-r--r-- | arch/riscv64/kernel/vmem.c | 90 |
4 files changed, 79 insertions, 19 deletions
diff --git a/arch/riscv64/kernel/entry.S b/arch/riscv64/kernel/entry.S index f894e0d..48851d4 100644 --- a/arch/riscv64/kernel/entry.S +++ b/arch/riscv64/kernel/entry.S @@ -92,6 +92,9 @@ continue_trap: save_callee save_caller + csrr t0, CSR_SEPC + sr t0, offsetof_exec(tp) + mv a0, s10 /* get actual kernel stack into sp */ mv sp, tp @@ -117,6 +120,7 @@ handle_exception: csrr a0, CSR_SEPC csrr a1, CSR_STVAL csrr a2, CSR_SCAUSE + sr a0, offsetof_exec(tp) mv sp, tp call riscv_handle_exception diff --git a/arch/riscv64/kernel/except.c b/arch/riscv64/kernel/except.c index e46b584..2525716 100644 --- a/arch/riscv64/kernel/except.c +++ b/arch/riscv64/kernel/except.c @@ -1,5 +1,6 @@ #include <kmi/types.h> #include <kmi/panic.h> +#include <kmi/debug.h> #include <kmi/vmem.h> #include <kmi/bkl.h> diff --git a/arch/riscv64/kernel/proc.c b/arch/riscv64/kernel/proc.c index 3ae2e15..ba5c8e7 100644 --- a/arch/riscv64/kernel/proc.c +++ b/arch/riscv64/kernel/proc.c @@ -48,7 +48,8 @@ void run_init(struct tcb *t, vm_t fdt, vm_t initrd) clone_uvmem(r->proc.vmem, t->rpc.vmem); flush_tlb_all(); - vm_t stack_top = t->rpc_stack - BASE_PAGE_SIZE; + /* lore, should probably be codified somewhere */ + vm_t stack_top = get_stack(t); info("jumping to %lx with sp = %lx\n", (long)t->callback, stack_top); bkl_unlock(); diff --git a/arch/riscv64/kernel/vmem.c b/arch/riscv64/kernel/vmem.c index d66ddec..a1ca54e 100644 --- a/arch/riscv64/kernel/vmem.c +++ b/arch/riscv64/kernel/vmem.c @@ -12,6 +12,7 @@ #include <kmi/vmem.h> #include <kmi/mem.h> #include <kmi/debug.h> +#include <arch/proc.h> #include <arch/cpu.h> #include "pages.h" #include "arch.h" @@ -598,7 +599,8 @@ stat_t setup_rpc_stack(struct tcb *t) { /* by default rpc stack is marked inaccessible to generate segfaults on * access so as to ease stack usage tracking */ - vmflags_t flags = VM_V | VM_R | VM_W | VM_U; + vmflags_t flags = VM_V | VM_R | + VM_W /*| VM_U note how this is missing */; for (size_t i = 0; i < rpc_pages; ++i) { pm_t page = alloc_page(BASE_PAGE); @@ -620,8 +622,12 @@ stat_t setup_rpc_stack(struct tcb *t) t->arch.rpc_leaf = (struct vmem *)__find_vmem(t->rpc.vmem, RPC_STACK_BASE, NULL); - /* we count downward in base pages */ - t->arch.rpc_idx = rpc_pages; + /* we count downward in base pages, the top page is *always* reserved */ + t->arch.rpc_idx = rpc_pages - 1; + + /* mark our stack region inaccessible to userspace */ + vm_t stack_top = t->rpc_stack - BASE_PAGE_SIZE; + set_stack(t, stack_top); return OK; } @@ -640,7 +646,7 @@ void destroy_rpc_stack(struct tcb *t) void reset_rpc_stack(struct tcb *t) { t->rpc_stack = RPC_STACK_BASE + (BASE_PAGE_SIZE * rpc_pages); - t->arch.rpc_idx = rpc_pages; + t->arch.rpc_idx = rpc_pages - 1; } bool rpc_stack_empty(pm_t addr) @@ -658,37 +664,85 @@ vm_t rpc_position(struct tcb *t) return RPC_STACK_BASE + (BASE_PAGE_SIZE * t->arch.rpc_idx); } -void mark_rpc_invalid(struct tcb *t, vm_t top) +/* these following stack handling routines are pretty mind-bending + * unfortunately, might there be a better way? */ + +bool in_rpc_stack(struct tcb *t, vm_t addr) +{ + return addr >= RPC_STACK_BASE + && addr < RPC_STACK_BASE + BASE_PAGE_SIZE * t->arch.rpc_idx; +} + +void close_rpc(struct tcb *t) { struct vmem *b = t->arch.rpc_leaf; int top_idx = t->arch.rpc_idx; - int bottom_idx = (top - RPC_STACK_BASE) / BASE_PAGE_SIZE; - assert(bottom_idx < top_idx); - while (top_idx != bottom_idx) { + /* absolute max iter count */ + for (; top_idx < (int)rpc_pages; --top_idx) { + /* mark inaccessible until we reach the first inaccessible + * region */ pm_t *pte = (pm_t *)&b->leaf[top_idx]; + if (!(pte_flags(*pte) & VM_U)) + break; + /* make page not accessible from userspace */ clear_bits(*pte, vp_flags(VM_U)); - top_idx--; } + /* make page following closed region accessible so we can avoid an + * unnecessary page fault */ + pm_t *pte = (pm_t *)&b->leaf[top_idx]; + set_bits(*pte, vp_flags(VM_U)); t->arch.rpc_idx = top_idx; } -void mark_rpc_valid(struct tcb *t, vm_t bottom) +void shrink_rpc(struct tcb *t) { struct vmem *b = t->arch.rpc_leaf; - int bottom_idx = t->arch.rpc_idx; - int top_idx = (bottom - RPC_STACK_BASE) / BASE_PAGE_SIZE; - assert(bottom_idx <= top_idx); + int top_idx = t->arch.rpc_idx; + + for (; top_idx > 0; ++top_idx) { + pm_t *pte = (pm_t *)&b->leaf[top_idx]; + if (!(pte_flags(*pte) & VM_U)) + break; + + clear_bits(*pte, vp_flags(VM_U)); + } + + t->arch.rpc_idx = top_idx; +} + +void open_rpc(struct tcb *t, vm_t top) +{ + assert(is_aligned(top, BASE_PAGE_SIZE)); + struct vmem *b = t->arch.rpc_leaf; + int old_idx = t->arch.rpc_idx; + int new_idx = (top - RPC_STACK_BASE) / BASE_PAGE_SIZE; + assert(new_idx >= old_idx); + + /* always stop one before the page index indicated, might be kind of + * easy to mess up */ + for (int i = old_idx; i < new_idx - 1; ++i) { + pm_t *pte = (pm_t *)&b->leaf[i]; + set_bits(*pte, vp_flags(VM_U)); + } + + t->arch.rpc_idx = new_idx - 1; +} + +void grow_rpc(struct tcb *t, vm_t top) +{ + assert(is_aligned(top, BASE_PAGE_SIZE)); + struct vmem *b = t->arch.rpc_leaf; + int top_idx = t->arch.rpc_idx; + int bottom_idx = (top - RPC_STACK_BASE) / BASE_PAGE_SIZE; + assert (top_idx >= bottom_idx); - while (top_idx != bottom_idx) { - pm_t *pte = (pm_t *)&b->leaf[bottom_idx]; + for (int i = bottom_idx; i < top_idx; ++i) { + pm_t *pte = (pm_t *)&b->leaf[i]; /* make page accessible from userspace */ set_bits(*pte, vp_flags(VM_U)); - /* clear used bits */ - clear_bits(*pte, vp_flags(VM_A | VM_D)); - bottom_idx++; } t->arch.rpc_idx = bottom_idx; |
