aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-10-30 13:34:18 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2024-11-01 10:27:36 +0200
commitf139fff6ae7063c1965fa3085bb2585d7d838d72 (patch)
tree7ee9f7c6a1ee09dba93c086cd66861474b821c97 /arch
parentb576c1d477bf476f277d32ecf60c312e4a97490d (diff)
downloadkmi-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.S4
-rw-r--r--arch/riscv64/kernel/except.c1
-rw-r--r--arch/riscv64/kernel/proc.c3
-rw-r--r--arch/riscv64/kernel/vmem.c90
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;