From 5f813d49a08cf3c3f8cf6c422cfb6587df575f62 Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Sat, 26 Sep 2026 17:11:50 -0400 Subject: add docs for syscalls. make syscall code kind-of cleaner --- api/error.h | 3 + api/init.h | 19 ++- api/obj.h | 14 ++- api/syscall.h | 129 ++++++++----------- arch/x86_64/hal/obj.c | 18 ++- arch/x86_64/hal/paging.c | 105 +++++++++++----- arch/x86_64/hal/paging.h | 8 +- arch/x86_64/hal/process.c | 8 +- arch/x86_64/sys/serial.c | 39 ------ arch/x86_64/sys/syscall.c | 48 +++---- arch/x86_64/sys/syscall.h | 2 +- arch/x86_64/sys/syscall_serial.c | 33 +++++ boot/limine/memorymap.c | 41 +++--- config.h | 2 + config.mk | 1 + doc/syscall.md | 264 +++++++++++++++++++++++++++++++++++++++ hal/memory.h | 10 +- hal/process.h | 2 +- sys/link.c | 56 ++++++--- sys/link.h | 24 +++- sys/lockstack.c | 30 +++++ sys/lockstack.h | 18 +++ sys/syscall.c | 105 ++++++++-------- sys/syscall.h | 45 ++++--- sys/syscall_objdir.c | 19 ++- sys/syscall_pagedir.c | 170 ++++++++++++++++++------- sys/syscall_untyped.c | 68 ++++++---- sys/syscall_vtt.c | 20 ++- 28 files changed, 896 insertions(+), 405 deletions(-) delete mode 100644 arch/x86_64/sys/serial.c create mode 100644 arch/x86_64/sys/syscall_serial.c create mode 100644 doc/syscall.md create mode 100644 sys/lockstack.c create mode 100644 sys/lockstack.h diff --git a/api/error.h b/api/error.h index 5e0e936..de7d4b2 100644 --- a/api/error.h +++ b/api/error.h @@ -15,5 +15,8 @@ #define EBUSY 12 #define EEMPTY 13 #define EFULL 14 +#define EOVERFLOW 15 +#define EBADCALL 16 +#define EPERM 17 #endif diff --git a/api/init.h b/api/init.h index 73b19e4..e92c910 100644 --- a/api/init.h +++ b/api/init.h @@ -4,26 +4,33 @@ #include enum { - ROOTDIR_DIR_I = 0, + ROOTDIR_NULL_I = 0, + ROOTDIR_DIR_I, ROOTDIR_PROCESSORS_I, ROOTDIR_PAGEDIR_I, ROOTDIR_UNTYPED_I, ROOTDIR_HWMEMORY_I, ROOTDIR_PCB_I, - ROOTDIR_IOPB_I, ROOTDIR_INTERRUPTS_I, ROOTDIR_INITRD_I, ROOTDIR_MESSAGE_I, + ROOTDIR_FRAMEBUFFER_I, + ROOTDIR_VIRTTERM_I, + _ROOTDIR_LAST_I }; +#ifdef __x86_64__ +enum { + ROOTDIR_IOPB_I = _ROOTDIR_LAST_I, + ROOTDIR_SERIAL_COM_I, + _ROOTDIR_LAST_ARCH_I +}; +#endif + struct init_payload { void *rsdp; uintptr_t brk; }; -#define ROOTDIR_SERIAL_COM_I 0x80 -#define ROOTDIR_FRAMEBUFFER_I 0x81 -#define ROOTDIR_VIRTTERM_I 0x82 - #endif diff --git a/api/obj.h b/api/obj.h index 04513c1..6e9ddc6 100644 --- a/api/obj.h +++ b/api/obj.h @@ -10,9 +10,9 @@ enum JOVE_OBJ_OBJDIR, JOVE_OBJ_PAGEDIR, JOVE_OBJ_PROCESSOR, - JOVE_OBJ_HWMEMORY, + JOVE_OBJ_SHMEMORY, JOVE_OBJ_INT_HANDLE, - JOVE_OBJ_PROCESS, + JOVE_OBJ_PCB, JOVE_OBJ_INITRD_FILE, JOVE_OBJ_FRAMEBUFFER, JOVE_OBJ_VIRTTERM, @@ -20,6 +20,16 @@ enum JOVE_OBJ_LINK, }; + +/*Link can read object states and map page frames as read only*/ +#define JOVE_PERM_READ 1 +/*Link can write object states and map page frames as writeable*/ +#define JOVE_PERM_WRITE 2 +/*Link can untype linked objects, split untyped memory, and retype untyped linked object.*/ +#define JOVE_PERM_MUTATE 4 + +#define JOVE_PERM_ALL 7 + #define OBJDIR_NUM_ENTRIES (0x1000 / sizeof(uintmax_t)) typedef uint16_t objpath_part_t; diff --git a/api/syscall.h b/api/syscall.h index 4bb2eb2..1cdc941 100644 --- a/api/syscall.h +++ b/api/syscall.h @@ -38,35 +38,21 @@ struct syscall_generic_objpath objpath_part_t path[]; }; -/* The kernel will return the physical memory address of this untyped object. */ -#define SYSCALL_UNTYPED_ADDRESS 0 -/* The kernel will return the size of this untyped object. */ -#define SYSCALL_UNTYPED_SIZE 1 - -/* If newtype is not a valid JOVE object, the kernel will return EBADARG. - * If the untyped object is too small for this object, the kernel will return ETOOSMALL. - * If the untyped object is too big for this object, the kernel will return ETOOBIG. - * New objects will be initialized with default values. - * */ -#define SYSCALL_UNTYPED_RETYPE 2 -struct syscall_untyped_retype +enum { - uint16_t newtype; + _SYSCALL_UNTYPED_BADCALL = 0, + SYSCALL_UNTYPED_ADDRESS, + SYSCALL_UNTYPED_SIZE, + SYSCALL_UNTYPED_SPLIT, + SYSCALL_UNTYPED_MERGE, + SYSCALL_UNTYPED_RETYPE, }; -/* Splits the tail of the untyped object into another untyped object with [bytes] length. - * If bytes is less than JOVE_UNTYPED_MINSIZE, the kernel will return ETOOSMALL. - * If the syscall message is too small for dest_path, the kernel will return ETOOSMALL. - * If dest_path does not target a JOVE_OBJ_NONE object, the kernel will return EBADOBJ. - * Destination path will be occupied by the untyped object created by the split. - * */ -#define SYSCALL_UNTYPED_SPLIT 3 -/* Follows rules declared above syscall_generic_objpath. - * If dest_path does not target a JOVE_OBJ_UNTYPED object, the kernel will return EBADPATH. - * If the dest untyped object is not adjacent to the target object, the kernel will return EBADOBJ. - * Destination path will be set to JOVE_OBJ_NONE and target untyped will grow to include the object. - * */ -#define SYSCALL_UNTYPED_MERGE 4 +#define SYSCALL_PERM_UNTYPED_ADDRESS JOVE_PERM_READ +#define SYSCALL_PERM_UNTYPED_SIZE JOVE_PERM_READ +#define SYSCALL_PERM_UNTYPED_SPLIT (JOVE_PERM_WRITE | JOVE_PERM_MUTATE) +#define SYSCALL_PERM_UNTYPED_MERGE (JOVE_PERM_WRITE | JOVE_PERM_MUTATE) + struct syscall_untyped_split { size_t bytes; @@ -74,71 +60,56 @@ struct syscall_untyped_split objpath_part_t dest_path[]; }; -/* Follows rules declared above syscall_generic_objpath. - * Returns the object type at path. - * */ -#define SYSCALL_OBJDIR_OBJTYPE 0 +enum +{ + _SYSCALL_OBJDIR_BADCALL = 0, + SYSCALL_OBJDIR_OBJTYPE, +}; -/* - * If virtual_address does not have a page table, the kernel will return ENOMAP. - * If virtual_address already has a mapping, the kernel will return EEXIST. - * Follows the rules defined above syscall_pagedir_map. - * Maps the untyped page frame to the page table at virtual_address with the passed flags bits. - * */ -#define SYSCALL_PAGEDIR_MAP_FRAME 0 +#define SYSCALL_PERM_OBJDIR_OBJTYPE JOVE_PERM_READ + +enum +{ + _SYSCALL_PAGEDIR_NONE = 0, + SYSCALL_PAGEDIR_MAP_FRAME, + SYSCALL_PAGEDIR_MAP_TABLE, + SYSCALL_PAGEDIR_MAP_SHMEM, + SYSCALL_PAGEDIR_UNMAP_FRAME, + SYSCALL_PAGEDIR_UNMAP_TABLE, + SYSCALL_PAGEDIR_UNMAP_SHMEM, +}; + +#define SYSCALL_PERM_PAGEDIR_MAP_FRAME (JOVE_PERM_READ | JOVE_PERM_WRITE) +#define SYSCALL_PERM_PAGEDIR_MAP_TABLE (JOVE_PERM_READ | JOVE_PERM_WRITE) +#define SYSCALL_PERM_PAGEDIR_MAP_SHMEM (JOVE_PERM_READ | JOVE_PERM_WRITE) +#define SYSCALL_PERM_PAGEDIR_UNMAP_FRAME (JOVE_PERM_READ | JOVE_PERM_WRITE) +#define SYSCALL_PERM_PAGEDIR_UNMAP_TABLE (JOVE_PERM_READ | JOVE_PERM_WRITE) +#define SYSCALL_PERM_PAGEDIR_UNMAP_SHMEM (JOVE_PERM_READ | JOVE_PERM_WRITE) -/* If virtual_address already has a page table, the kernel will return EHASMAP. - * Follows the rules defined above syscall_pagedir_map. - * Creates a page table using the untyped object for memory allocation at virtual_address. - * Flags bits are always set to writeable and executable. - * */ -#define SYSCALL_PAGEDIR_MAP_TABLE 1 - -/* If virtual_address is above the JOVE_USER_MEMORY_LIMIT, the kernel will return EBADARG. - * If the message is too small for untyped_path, the kernel will return ETOOSMALL. - * If untyped_path does not point to a valid JOVE_OBJ_UNTYPED, the kernel will return EBADOBJ. - * If the untyped object is not aligned to 0x1000, the kernel will return EALIGN. - * If the untyped object is not sized to 0x1000, the kernel will return EBADSIZE. - * - * */ struct syscall_pagedir_flags { uint8_t writeable : 1; uint8_t executable : 1; uint8_t flg_unused : 6; }; + struct syscall_pagedir_map { - struct syscall_pagedir_flags flags; - uintptr_t virtual_address; + struct syscall_pagedir_flags page_flags; uint16_t untyped_pathlen; + uintptr_t virtual_address; objpath_part_t untyped_path[]; }; -/**If a page frame is present at the virtual address, the kernel will: - * mark the page frame as not present. - * untype the page frame and move it to the none path. - * return 0. - * If a page frame is not present at the virtual address, the kernel will return EEMPTY. - * Follows the rules defined by struct syscall_pagedir_unmap - * */ -#define SYSCALL_PAGEDIR_UNMAP_FRAME 2 - -/**If a page table is present at the virtual address, one of two things will happen: - * If the page table has present entries, the kernel will return EBUSY. - * Otherwise, the kernel will: - * mark the page table as not present. - * untype the page frame and move it to the none path. - * return 0. - * If a page table is not present at the virtual address, the kernel will return EEMPTY. - * Follows the rules defined by the struct syscall_pagedir_unmap - * */ -#define SYSCALL_PAGEDIR_UNMAP_TABLE 3 +struct syscall_pagedir_map_shmem +{ + struct syscall_pagedir_flags page_flags; + uint8_t page_offset; + uint16_t shmem_pathlen; + uintptr_t virtual_address; + objpath_part_t shmem_path[]; +}; -/**If the virtual address is above JOVE_USER_MEMORY_LIMIT, the kernel will return EBADARG. - * If none_pathlen exceeds the length of the message, the kernel will return ETOOBIG. - * If none_path does not point to a JOVE_OBJ_NONE object, the kernel will return EBADOBJ. - * */ struct syscall_pagedir_unmap { uintptr_t virtual_address; @@ -146,6 +117,10 @@ struct syscall_pagedir_unmap objpath_part_t none_path[]; }; -#define SYSCALL_VTT_WRITE 0 +enum +{ + _SYSCALL_VTT_NONE = 0, + SYSCALL_VTT_WRITE +}; #endif diff --git a/arch/x86_64/hal/obj.c b/arch/x86_64/hal/obj.c index cb0e13d..9844a54 100644 --- a/arch/x86_64/hal/obj.c +++ b/arch/x86_64/hal/obj.c @@ -79,7 +79,7 @@ objdir_peeklocal( jove_owned_obj_t *objdir_obj, uint16_t entry) { - if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) { + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { errno = EBADOBJ; return (jove_obj_t) { 0 }; } @@ -88,7 +88,7 @@ objdir_peeklocal( return (jove_obj_t) { 0 }; } - jove_objdir_t *objtab = obj_deref_linked(objdir_obj); + jove_objdir_t *objtab = obj_deref(objdir_obj); return objtab->entries[entry]; } @@ -97,14 +97,17 @@ objdir_getlocal( jove_owned_obj_t *objdir_obj, uint16_t entry) { - if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) { + while(obj_gettype(objdir_obj) == JOVE_OBJ_LINK) { + objdir_obj = link_deref(objdir_obj); + } + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { reterr(EBADOBJ); } if(entry >= JOVE_OBJDIR_ENTRIES) { reterr(EBADPATH); } - jove_objdir_t *objtab = obj_deref_linked(objdir_obj); + jove_objdir_t *objtab = obj_deref(objdir_obj); return obj_take(&objtab->entries[entry]); } @@ -113,14 +116,17 @@ objdir_trygetlocal( jove_owned_obj_t *objdir_obj, uint16_t entry) { - if(obj_gettype_linked(objdir_obj) != JOVE_OBJ_OBJDIR) { + while(obj_gettype(objdir_obj) == JOVE_OBJ_LINK) { + objdir_obj = link_deref(objdir_obj); + } + if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { reterr(EBADOBJ); } if(entry >= JOVE_OBJDIR_ENTRIES) { reterr(EBADPATH); } - jove_objdir_t *objtab = obj_deref_linked(objdir_obj); + jove_objdir_t *objtab = obj_deref(objdir_obj); return obj_trytake(&objtab->entries[entry]); } diff --git a/arch/x86_64/hal/paging.c b/arch/x86_64/hal/paging.c index 9947e9c..2fbf26c 100644 --- a/arch/x86_64/hal/paging.c +++ b/arch/x86_64/hal/paging.c @@ -106,7 +106,7 @@ s_pagedir_get_pml1(page_t *pml4, uintptr_t vptr) } int pagedir_map_frame(page_t *pml4, - uintptr_t pptr, uintptr_t vptr, + uintptr_t pptr, uintptr_t vptr, uintmax_t flg) { page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); @@ -121,41 +121,35 @@ int pagedir_map_frame(page_t *pml4, return 0; } -int pagedir_map_untyped_frame( - jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, - uintptr_t vptr, struct syscall_pagedir_flags flg) +int pagedir_map_shmem(page_t *pml4, + uintptr_t pptr, uintptr_t vptr, + struct syscall_pagedir_flags flg) { - page_t *pml4 = obj_deref(tgt); - uintptr_t frame = obj_getvalue(untyped_obj); - - return pagedir_map_frame(pml4, frame, vptr, - (flg.writeable ? PAGE_WRITEABLE : 0) | - PAGE_USER | - (flg.executable ? PAGE_XD : 0)); + uintmax_t real_flg = PAGE_USER | PAGE_SHMEM; + if(flg.writeable) { + real_flg |= PAGE_WRITEABLE; + } + if(!flg.executable) { + real_flg |= PAGE_XD; + } + return pagedir_map_frame(pml4, pptr, vptr, real_flg); } -int pagedir_unmap_untyped_frame( - jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) +int pagedir_map_untyped_frame( + jove_owned_obj_t *tgt, jove_perm_obj_t *untyped, + uintptr_t vptr, struct syscall_pagedir_flags flg) { page_t *pml4 = obj_deref(tgt); - size_t pml4i = PML4I(vptr); - if(!pml4[pml4i].p) return ENOMAP; - - page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); - size_t pml1i = PML1I(vptr); - if(!pml1[pml1i].p) return ENOMAP; - - uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12); - - obj_settype(dst, JOVE_OBJ_UNTYPED); - obj_setvalue(dst, untyped_pptr); - - jove_untyped_t *untyped_data = obj_deref(dst); - untyped_data->limit = 0x1000; - __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + if(flg.writeable && (untyped->permissions & JOVE_PERM_WRITE) == 0) { + kprintf("%s: Untyped object flagged for writeable mapping missing write permissions!\n", __func__); + return -EPERM; + } - return 0; + uintptr_t frame = obj_getvalue(untyped->obj); + return pagedir_map_frame(pml4, frame, vptr, PAGE_USER | + (flg.writeable ? PAGE_WRITEABLE : 0) | + (flg.executable ? 0 : PAGE_XD)); } int pagedir_map_table(page_t *pml4, @@ -199,14 +193,63 @@ map_table: } int pagedir_map_untyped_table( - jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, uintptr_t vptr) + jove_owned_obj_t *tgt, jove_perm_obj_t *untyped, uintptr_t vptr) { page_t *pml4 = obj_deref(tgt); - uintptr_t frame = obj_getvalue(untyped_obj); + + if((untyped->permissions & JOVE_PERM_WRITE) == 0) { + kprintf("%s: Untyped object flagged for table mapping missing write permissions!\n", __func__); + return -EPERM; + } + uintptr_t frame = obj_getvalue(untyped->obj); return pagedir_map_table(pml4, frame, vptr); } +int pagedir_map_shmem_frame( + jove_owned_obj_t *tgt, jove_perm_obj_t *shmem, uint8_t page_offset, + uintptr_t vptr, struct syscall_pagedir_flags flg) +{ + page_t *pml4 = obj_deref(tgt); + + if(flg.writeable && (shmem->permissions & JOVE_PERM_WRITE) != 0) { + kprintf("%s: Shared memory object flagged for writeable mapping missing write permissions!\n", __func__); + return -EPERM; + } + + uintmax_t value = obj_getvalue(shmem->obj); + uintptr_t frame = value & ~0xFF; + frame += (uintmax_t)page_offset << 12; + + return pagedir_map_frame(pml4, frame, vptr, PAGE_USER | + (flg.writeable ? PAGE_WRITEABLE : 0) | + (flg.executable ? 0 : PAGE_XD)); +} + +int pagedir_unmap_untyped_frame( + jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) +{ + page_t *pml4 = obj_deref(tgt); + + size_t pml4i = PML4I(vptr); + if(!pml4[pml4i].p) return ENOMAP; + + page_t *pml1 = s_pagedir_get_pml1(pml4, vptr); + size_t pml1i = PML1I(vptr); + if(!pml1[pml1i].p) return ENOMAP; + + uintptr_t untyped_pptr = (pml1[pml1i].paddr << 12); + + obj_settype(dst, JOVE_OBJ_UNTYPED); + obj_setvalue(dst, untyped_pptr); + + jove_untyped_t *untyped_data = obj_deref(dst); + untyped_data->limit = 0x1000; + __asm__ volatile("invlpg (%0)":: "r"(vptr): "memory"); + + return 0; +} + int pagedir_unmap_untyped_table( jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr) { diff --git a/arch/x86_64/hal/paging.h b/arch/x86_64/hal/paging.h index 5b7260c..becf353 100644 --- a/arch/x86_64/hal/paging.h +++ b/arch/x86_64/hal/paging.h @@ -17,7 +17,8 @@ typedef union page_table_entry uint8_t d : 1; uint8_t ps : 1; uint8_t g : 1; - uint8_t ign_0 : 2; + uint8_t shm : 1; + uint8_t ign_0 : 1; uint8_t r : 1; uint64_t paddr : 35; uint8_t ign_1 : 4; @@ -35,8 +36,9 @@ typedef union page_table_entry #define PAGE_ACCESSED 0b100000 #define PAGE_DIRTY 0b1000000 #define PAGE_PS 0b10000000 -#define PAGE_GLOBAL 0b000000000 -#define PAGE_XD (0ULL << 63) +#define PAGE_GLOBAL 0b100000000 +#define PAGE_SHMEM 0b1000000000 +#define PAGE_XD (1ULL << 63) extern void *_kernel_physptr; diff --git a/arch/x86_64/hal/process.c b/arch/x86_64/hal/process.c index f30d703..aa51f45 100644 --- a/arch/x86_64/hal/process.c +++ b/arch/x86_64/hal/process.c @@ -22,7 +22,7 @@ process_current(void) pcb_t* pcb_from_obj(jove_owned_obj_t *obj) { - if(obj_gettype(obj) != JOVE_OBJ_PROCESS) { + if(obj_gettype(obj) != JOVE_OBJ_PCB) { reterr(EBADOBJ); } return obj_deref(obj); @@ -34,10 +34,10 @@ pcb_pid(pcb_t *pcb) return pcb->pid; } -jove_owned_obj_t* +jove_obj_t* pcb_rootdir(pcb_t *pcb) { - return obj_take(pcb->rootdir); + return pcb->rootdir; } void @@ -62,7 +62,7 @@ processing_setup(void (*process_main)) { jove_owned_obj_t *process_obj = objdir_getlocal(_rootdir_obj, ROOTDIR_PCB_I); - obj_settype(process_obj, JOVE_OBJ_PROCESS); + obj_settype(process_obj, JOVE_OBJ_PCB); obj_setvalue(process_obj, (uintptr_t)s_init_pcb); proc->pcb_obj = obj_release(process_obj); diff --git a/arch/x86_64/sys/serial.c b/arch/x86_64/sys/serial.c deleted file mode 100644 index 12db6fd..0000000 --- a/arch/x86_64/sys/serial.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "jove.h" -#include "lib/printf.h" -#include "syscall.h" -#include "arch/x86_64/hal/serial_com.h" - -static int -s_syscall_serial_write( - jove_owned_obj_t *serial_com, - size_t payload_bytes, - void *payload_data) -{ - size_t bytes_needed = sizeof(struct syscall_generic_write); - CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for this syscall!"); - - struct syscall_generic_write *payload = payload_data; - bytes_needed += payload->len * 2; - CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for write buffer!"); - - return serial_com_write(serial_com, payload->data, payload->len); -} - -int -_syscall_handle_serial( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload_data) -{ - switch(header->callid) { - case 0: - return s_syscall_serial_write(target_obj, bytes_left, payload_data); - default: - kprintf("syscall_serial: serial com object does not support syscall %i\n", header->callid); - return EOOB; - } -} diff --git a/arch/x86_64/sys/syscall.c b/arch/x86_64/sys/syscall.c index 53351e7..a694674 100644 --- a/arch/x86_64/sys/syscall.c +++ b/arch/x86_64/sys/syscall.c @@ -10,24 +10,17 @@ syscall_handle_t s_arch_handles[128] = { }; int -_syscall_handle_arch( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload) +_syscall_handle_arch(syscall_context_t *ctx) { - uint8_t target_type = obj_gettype(target_obj) - 0x80; + uint8_t target_type = obj_gettype(ctx->target.obj) - 0x80; syscall_handle_t call_handle = s_arch_handles[target_type]; if(call_handle == NULL) { kprintf("syscall: Process %i tried to call syscall on object %P which doesn't support syscalls!\n", - pcb_pid(obj_deref(pcb_obj)), header->path, header->pathlen); - return EBADOBJ; + pcb_pid(obj_deref(ctx->pcb)), ctx->header->path, ctx->header->pathlen); + return -EBADOBJ; } - return call_handle(pcb_obj, objdir, message_obj, target_obj, header, bytes_left, payload); + return call_handle(ctx); } __attribute__((naked)) @@ -38,32 +31,29 @@ void _syscall_entry(void) movq %%gs:%c[pcb], %%rax; \ movq %%rsp, %%rdx; \ movq %c[ksp](%%rax), %%rsp; \ + pushq %%rcx; \ pushq %%rdx; \ pushq %%r11; \ - pushq %%rbx; \ - pushq %%rcx; \ pushq %%rbp; \ - pushq %%r12; \ - pushq %%r13; \ - pushq %%r14; \ - pushq %%r15; \ callq syscall_handler; \ swapgs; \ - popq %%r15; \ - popq %%r14; \ - popq %%r13; \ - popq %%r12; \ - popq %%rbp; \ - popq %%rcx; \ - popq %%rbx; \ - xorq %%rdx, %%rdx; \ + xorq %%r15, %%r15; \ + xorq %%r14, %%r14; \ + xorq %%r13, %%r13; \ + xorq %%r12, %%r12; \ + xorq %%r10, %%r10; \ + xorq %%r9, %%r9; \ + xorq %%r8, %%r8; \ xorq %%rsi, %%rsi; \ xorq %%rdi, %%rdi; \ - xorq %%r8, %%r8; \ - xorq %%r9, %%r9; \ - xorq %%r10, %%r10; \ + xorq %%rbp, %%rbp; \ + xorq %%rdx, %%rdx; \ + xorq %%rcx, %%rcx; \ + xorq %%rbx, %%rbx; \ + popq %%rbp; \ popq %%r11; \ popq %%rsp; \ + popq %%rcx; \ sysretq;" :: [pcb] "i"(offsetof(processor_t, pcb)), diff --git a/arch/x86_64/sys/syscall.h b/arch/x86_64/sys/syscall.h index 868ce0b..34f6a2a 100644 --- a/arch/x86_64/sys/syscall.h +++ b/arch/x86_64/sys/syscall.h @@ -3,7 +3,7 @@ #include "sys/syscall.h" -int _syscall_handle_serial(SYSCALL_FUNCTION_ARGS); +int _syscall_handle_serial(syscall_context_t *ctx); #define SYSCALL_SERIAL_COM_WRITE 0 diff --git a/arch/x86_64/sys/syscall_serial.c b/arch/x86_64/sys/syscall_serial.c new file mode 100644 index 0000000..786a78b --- /dev/null +++ b/arch/x86_64/sys/syscall_serial.c @@ -0,0 +1,33 @@ +#include "jove.h" +#include "lib/printf.h" +#include "sys/syscall.h" +#include "syscall.h" +#include "arch/x86_64/hal/serial_com.h" + +static int +s_syscall_serial_write( + jove_owned_obj_t *serial_com, + size_t payload_bytes, + void *payload_data) +{ + size_t bytes_needed = sizeof(struct syscall_generic_write); + CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for this syscall!"); + + struct syscall_generic_write *payload = payload_data; + bytes_needed += payload->len * 2; + CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for write buffer!"); + + return serial_com_write(serial_com, payload->data, payload->len); +} + +int +_syscall_handle_serial(syscall_context_t *ctx) +{ + switch(ctx->header->callid) { + case SYSCALL_SERIAL_COM_WRITE: + return s_syscall_serial_write(ctx->target.obj, ctx->bytes_left, ctx->payload); + default: + kprintf("syscall_serial: serial com object does not support syscall %i\n", ctx->header->callid); + return -EBADCALL; + } +} diff --git a/boot/limine/memorymap.c b/boot/limine/memorymap.c index 25dcc61..a8841e2 100644 --- a/boot/limine/memorymap.c +++ b/boot/limine/memorymap.c @@ -49,13 +49,17 @@ mem_setup_untyped(void) uintptr_t highest_phys = 0; for(size_t i = 0; i < _limine_memmap_resp->entry_count; i++) { struct limine_memmap_entry *entry = _limine_memmap_resp->entries[i]; - kprintf("Limine: %p : %p %s\n", entry->base, entry->length, limine_mmap_entry_type_str[entry->type]); if(entry->type == LIMINE_MEMMAP_USABLE || entry->type == LIMINE_MEMMAP_ACPI_RECLAIMABLE || entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE) { - + if(untyped_i > JOVE_OBJDIR_ENTRIES){ + kprintf("%s: Provided memory map exceeds kernel limits. Some memory may not be accessable.", __func__); + break; + } + + klogf("%p : %p %s\n", entry->base, entry->length, limine_mmap_entry_type_str[entry->type]); if(entry->base == 0) continue; if(entry->base + entry->length > highest_phys) highest_phys = entry->base + entry->length; @@ -68,27 +72,30 @@ mem_setup_untyped(void) untyped_data->limit = entry->length; obj_release(untyped_obj); } - - if(untyped_i > MEMMAP_MAX_ENTRIES){ - kprintf("!!!Provided memory map exceeds kernel limits. Some memory may not be accessable!!!"); - break; - } } if(entry->type == LIMINE_MEMMAP_RESERVED | entry->type == LIMINE_MEMMAP_ACPI_NVS | entry->type == LIMINE_MEMMAP_ACPI_TABLES) { - size_t hw_pages = entry->length >> 12; - if(hw_pages > 4095) { - klogf("HW memory page is too big!\n", ""); + intmax_t hw_pages = entry->length >> 12; + uintptr_t base = entry->base; + while(hw_pages > 0) { + if(hwmem_i >= JOVE_OBJDIR_ENTRIES) { + kprintf("%s: Reserved memory region exceeds indexing limits!\n", __func__); + break; + } + + size_t pages = hw_pages > 4095 ? 4095 : hw_pages; + klogf("%p : %p RESERVED\n", base, ((pages + 1) << 12)); + + jove_owned_obj_t *hwmem_obj = obj_take(&s_hwmemory_objdir.entries[hwmem_i++]); + obj_settype(hwmem_obj, JOVE_OBJ_SHMEMORY); + obj_setvalue(hwmem_obj, entry->base | (entry->length >> 12)); + + obj_release(hwmem_obj); + hw_pages -= 4096; + base += (4096ULL << 12); } - - jove_owned_obj_t *hwmem_obj = obj_take(&s_hwmemory_objdir.entries[hwmem_i++]); - obj_settype(hwmem_obj, JOVE_OBJ_HWMEMORY); - obj_setvalue(hwmem_obj, entry->base | (entry->length >> 12)); - - obj_release(hwmem_obj); } } - kprintf("Highest physical address: %p\n", highest_phys); } diff --git a/config.h b/config.h index 02c4243..50f35c1 100644 --- a/config.h +++ b/config.h @@ -14,4 +14,6 @@ #define INIT_PROGRAM_PAGES_MAX 32 #define INIT_STACK_PAGES 2 +#define LOCKSTACK_MAX 64 + #endif diff --git a/config.mk b/config.mk index 760d264..7416c4e 100644 --- a/config.mk +++ b/config.mk @@ -5,6 +5,7 @@ CFLAGS = \ -fno-pic \ -g \ -MD \ + -mno-sse \ -D__$(TARGET_MACHINE)__ \ -D__$(TARGET_BOOTLOADER)__ \ -Iinclude \ diff --git a/doc/syscall.md b/doc/syscall.md new file mode 100644 index 0000000..9304785 --- /dev/null +++ b/doc/syscall.md @@ -0,0 +1,264 @@ +## Jove syscalls + +Every syscall in Jove is passed to the kernel via a `JOVE_OBJ_MESSAGE` object. + +To pass a message object to the kernel, the message object must be close to the root directory of the calling PCB. + +To resolve the message object, the kernel requires an object path and a path length encoded in argument registers. + +On x86_64, the encoding is as follows: + +| | Message Path | Message Path Length | +|----------|--------------|---------------------| +| Register | rdi | rsi | + +If the message path exceeds the width of the message path register, the kernel will return `-EBADPATH`. + +If the message path does not point to a `JOVE_OBJ_MESSAGE` object, the kernel will return `-EBADOBJ`. + +If the message path points to an object locked by a mutex, the kernel will return `-EBUSY`. + + +### Syscall header + +| Size (bytes) | 2 | 2 | path_len * 2 | +|--------------|---------|------------------------|--------------| +| Data | Call ID | Path length (path_len) | Target path | + +All system calls must start with these bytes at the start of the passed message object. + +1. `Call ID`: ID of the system call to invoke. +2. `Path length`: Length of the target path. +3. `Object path`: Path to the target object starting from the PCB's root directory. + +If the target path length exceeds the width of the message object, the kernel will return `-ETOOSMALL`. + +If the target path points to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. + +If the target object does not support the call id, the kernel will return `-EBADCALL`. + +Further behavior is specified by the target syscall specification. + +Target syscalls may have further required bytes in the message. + +If the syscall does not have the correct permissions for the syscall, the kernel will return `-ENOPERM`. + + +### JOVE_OBJ_UNTYPED + +| Syscall | Permissions Required | +|-------------------------|-----------------------------------| +| SYSCALL_UNTYPED_ADDRESS | JOVE_PERM_READ | +| SYSCALL_UNTYPED_SIZE | JOVE_PERM_READ | +| SYSCALL_UNTYPED_SPLIT | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | +| SYSCALL_UNTYPED_MERGE | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | +| SYSCALL_UNTYPED_RETYPE | JOVE_PERM_WRITE, JOVE_PERM_MUTATE | + +#### SYSCALL_UNTYPED_ADDRESS + +Returns the physical address of the untyped memory span. + +#### SYSCALL_UNTYPED_SIZE + +Returns the size of the untyped memory span. + +#### SYSCALL_UNTYPED_SPLIT + +Splits the untyped memory span into the destination path sized by the split size. + +| Data | Split size | Destination Path Length | Destination Path | +|--------------|----------------|-------------------------|------------------| +| Size (bytes) | sizeof(size_t) | 2 | path_len * 2 | + + +If the split size exceeds the size of the target untyped, the kernel will return `-ETOOBIG`. + +If the split size is less than `JOVE_UNTYPED_MINSIZE`, the kernel will return `-ETOOSMALL`. + +If the destination path length exceeds the size of the message, the kernel will return `-EBADPATH`. + +If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. + +#### SYSCALL_UNTYPED_MERGE + +Merges two adjacent untyped memory spans into one untyped memory span at the first untyped object. + +| Data | Untyped Path Length | Untyped Path | +|--------------|---------------------|--------------| +| Size (bytes) | 2 | path_len * 2 | + + +If the untyped path length exceeds the size of the message, the kernel will return `-EBADPATH`. + +If the untyped path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EBADOBJ`. + + +### JOVE_OBJ_OBJDIR + +| Syscall | Permissions Required | +|------------------------|----------------------| +| SYSCALL_OBJDIR_OBJTYPE | JOVE_PERM_READ | + +#### SYSCALL_OBJDIR_OBJTYPE + +Returns the object type at the given entry index. + +| Data | Entry Index | +|--------------|-------------| +| Size (bytes) | 2 | + +If the message is too small to hold the payload, the kernel will return `-ETOOSMALL`. + +If the entry index exceeds `JOVE_OBJDIR_ENTRIES`, the kernel returns `-EOOB`. + + +### JOVE_OBJ_PAGEDIR + +| Syscall | Target Permissions | Subject Permissions | Subject Conditional Permissions | +|-----------------------------|:-------------------------------:|:-------------------------------------------------:|:-------------------------------:| +| SYSCALL_PAGEDIR_MAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_MUTATE | JOVE_PERM_READ, JOVE_PERM_WRITE | +| SYSCALL_PAGEDIR_MAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | JOVE_PERM_READ, JOVE_PERM_WRITE, JOVE_PERM_MUTATE | | +| SYSCALL_PAGEDIR_MAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | JOVE_PERM_READ, JOVE_PERM_WRITE | +| SYSCALL_PAGEDIR_UNMAP_FRAME | JOVE_PERM_READ, JOVE_PERM_WRITE | | | +| SYSCALL_PAGEDIR_UNMAP_TABLE | JOVE_PERM_READ, JOVE_PERM_WRITE | | | +| SYSCALL_PAGEDIR_UNMAP_SHMEM | JOVE_PERM_READ, JOVE_PERM_WRITE | | | + + +#### SYSCALL_PAGEDIR_MAP_FRAME + +Attempts to map a given untyped memory span to the given virtual address with passed permissions. + +| Data | Page flags | Untyped Path Length | Virtual address | Untyped Path | +|--------------|------------|---------------------|-------------------|--------------| +| Size (bytes) | 1 | 2 | sizeof(void*) | path_len * 2 | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`. + +If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`. + +If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`. + +If the untyped object does not have `JOVE_PERM_MUTATE` and `JOVE_PERM_READ`, the kernel will return `-ENOPERM`. + +If the untyped object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`. + +If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`. + +If the virtual address already has a page mapping, the kernel will return `-EHASMAP`. + +Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`. + + +#### SYSCALL_PAGEDIR_MAP_TABLE + +Attempts to map a given untyped memory span as a table for mapping further page frames onto `virtual address`. + +| Data | Virtual address | Untyped Path Length | Untyped Path | +|--------------|-----------------|---------------------|--------------| +| Size (bytes) | sizeof(void*) | 2 | path_len * 2 | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the untyped path does not point to a `JOVE_OBJ_UNTYPED` object, the kernel will return `-EBADOBJ`. + +If the untyped object is not aligned to `0x1000` bytes, the kernel will return `-EALIGN`. + +If the untyped object is not exactly `0x1000` bytes wide, the kernel will return `-EBADSIZE`. + +If the untyped object does not have `JOVE_PERM_MUTATE`, `JOVE_PERM_READ`, and `JOVE_PERM_WRITE`, the kernel will return `-ENOPERM`. + +If the virtual address already has enough tables to allocate a page frame onto them, the kernel will return `-EHASMAP`. + +Successful mapping replaces the untyped object with a `JOVE_OBJ_NONE` object and returns `0`. + + +#### SYSCALL_PAGEDIR_MAP_SHMEM + +Attempts to map a shared memory page at `virtual address`. Does not consume the shared memory object. + +| Data | Page flags | Page offset | Shared Memory Path Length | Virtual address | Shared Memory Path | +|--------------|------------|-------------|---------------------------|-----------------|--------------------| +| Size (bytes) | 1 | 1 | 2 | sizeof(void*) | path_len * 2 | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the shmem path does not point to a `JOVE_OBJ_SHMEMORY` object, the kernel will return `-EBADOBJ`. + +If the shmem object does not have `JOVE_PERM_READ`, the kernel will return `-ENOPERM`. + +If the shmem object does not have `JOVE_PERM_WRITE` and the passed flags include the writeable bit, the kernel will return `-ENOPERM.`. + +If the virtual address does not have enough page table structures to support the page mapping, the kernel will return `-ENOMAP`. + +If the virtual address already has a page mapping, the kernel will return `-EHASMAP`. + +Successful mapping returns `0`. + + +#### SYSCALL_PAGEDIR_UNMAP_FRAME + +Attempts to remove an untyped memory mapping from the page table at `virtual address`. + +| Data | Virtual address | Destination Path Length | Destination Path | +|--------------|-----------------|-------------------------|------------------| +| Size (bytes) | sizeof(void*) | 2 | path_len * 2 | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`. + +If the virtual address does not have a page mapping, the kernel will return `-ENOMAP`. + +If the virtual address does not map to an untyped page frame, the kernel will return `-EBADARG`. + +Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0. + + +#### SYSCALL_PAGEDIR_UNMAP_TABLE + +Attempts to remove a page table mapping from the page directory heirarchy at `virtual address` + +| Data | Virtual address | Destination Path Length | Destination Path | +|--------------|-----------------|-------------------------|------------------| +| Size (bytes) | sizeof(void*) | 2 | path_len * 2 | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the destination path does not point to a `JOVE_OBJ_NONE` object, the kernel will return `-EFULL`. + +If the table mapping the virtual address has any occupied entries, the kernel will return `-EHASMAP`. + +If no table mapping exists for this virtual address, the kernel will return `-ENOMAP`. + +Successful unmapping fills the destination path with a page-sized `JOVE_OBJ_UNTYPED` object with correct permissions and return 0. + + +#### SYSCALL_PAGEDIR_UNMAP_SHMEM + +Attempts to unmap a shared memory page at `virtual address`. + +| Data | Virtual address | +|--------------|-----------------| +| Size (bytes) | sizeof(void*) | + +If the message is too small for the syscall payload, the kernel will return `-ETOOSMALL`. + +If the virtual address exceeds `JOVE_USER_MEMORY_LIMIT`, the kernel will return `-EOOB`. + +If the virtual address does not have a page frame associated with it, the kernel will return `-ENOMAP`. + +If the page frame pointed to by virtual address does not correspond to a shared memory frame, the kernel will return `-EBADOBJ`. + +Successful unmapping returns `0`. diff --git a/hal/memory.h b/hal/memory.h index 47dbf0a..6e685d6 100644 --- a/hal/memory.h +++ b/hal/memory.h @@ -1,3 +1,4 @@ +#include "sys/syscall.h" #ifndef _JOVE_HAL_MEMORY_H #define _JOVE_HAL_MEMORY_H 1 @@ -23,16 +24,21 @@ int untyped_merge(jove_owned_obj_t *a, jove_owned_obj_t *b); int untyped_retype(jove_owned_obj_t *tgt, uint8_t newtype); int pagedir_map_untyped_frame( - jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, + jove_owned_obj_t *tgt, jove_perm_obj_t *untyped_obj, uintptr_t vptr, struct syscall_pagedir_flags flg); int pagedir_map_untyped_table( - jove_owned_obj_t *tgt, jove_owned_obj_t *untyped_obj, + jove_owned_obj_t *tgt, jove_perm_obj_t *untyped_obj, uintptr_t vptr); +int pagedir_map_shmem_frame( + jove_owned_obj_t *tgt, jove_perm_obj_t *shmem_obj, uint8_t page_offset, + uintptr_t vptr, struct syscall_pagedir_flags flg); int pagedir_unmap_untyped_frame( jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr); int pagedir_unmap_untyped_table( jove_owned_obj_t *tgt, jove_owned_obj_t *dst, uintptr_t vptr); +int pagedir_unmap_shmem_frame( + jove_owned_obj_t *tgt, uintptr_t vptr); #endif diff --git a/hal/process.h b/hal/process.h index 63c800f..da3e050 100644 --- a/hal/process.h +++ b/hal/process.h @@ -24,6 +24,6 @@ jove_owned_obj_t *process_current(void); pid_t pcb_pid(pcb_t *pcb); /*Returns the root kernel object directory of this PCB. */ -jove_owned_obj_t *pcb_rootdir(pcb_t *pcb); +jove_obj_t *pcb_rootdir(pcb_t *pcb); #endif diff --git a/sys/link.c b/sys/link.c index 5be9457..592fe8f 100644 --- a/sys/link.c +++ b/sys/link.c @@ -2,31 +2,23 @@ #include "arch/x86_64/hal/obj.h" #include "hal/memory.h" -void* -obj_deref_linked(jove_owned_obj_t *obj) +uint8_t +link_gettype(jove_owned_obj_t *obj) { - switch(obj_gettype(obj)) { - case JOVE_OBJ_LINK: return obj_deref_linked(link_deref(obj)); - default: return obj_deref(obj); - } + return obj_gettype(link_deref(obj)); } uint8_t -obj_gettype_linked(jove_owned_obj_t *obj) +link_getperm(jove_owned_obj_t *link) { - switch(obj_gettype(obj)) { - case JOVE_OBJ_LINK: return obj_gettype_linked(link_deref(obj)); - default: return obj_gettype(obj); - } + struct obj_link *linkval = obj_deref(link); + return linkval->permissions; } uint64_t -obj_getvalue_linked(jove_owned_obj_t *obj) +link_getvalue(jove_owned_obj_t *obj) { - switch(obj_gettype(obj)) { - case JOVE_OBJ_LINK: return obj_getvalue_linked(link_deref(obj)); - default: return obj_getvalue(obj); - } + return obj_getvalue(link_deref(obj)); } jove_owned_obj_t* @@ -36,11 +28,41 @@ link_deref(jove_owned_obj_t *link) return obj_take(&linkval->obj); } -jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst) +jove_owned_obj_t* +link_try_deref(jove_owned_obj_t *link) +{ + struct obj_link *linkval = obj_deref(link); + return obj_trytake(&linkval->obj); +} + +jove_perm_obj_t +link_traverse(jove_owned_obj_t *link, lockstack_t *lockstack) +{ + jove_perm_obj_t perm_obj = { .obj = link, .permissions = JOVE_PERM_ALL }; + while(obj_gettype(perm_obj.obj) == JOVE_OBJ_LINK) { + perm_obj.permissions &= link_getperm(perm_obj.obj); + perm_obj.obj = lockstack_push(lockstack, link_deref(perm_obj.obj)); + } + return perm_obj; +} + +jove_perm_obj_t +link_try_traverse(jove_owned_obj_t *link, lockstack_t *lockstack) +{ + jove_perm_obj_t perm_obj = { .obj = link, .permissions = JOVE_PERM_ALL }; + while(perm_obj.obj != NULL && obj_gettype(perm_obj.obj) == JOVE_OBJ_LINK) { + perm_obj.permissions &= link_getperm(perm_obj.obj); + perm_obj.obj = lockstack_push(lockstack, link_deref(perm_obj.obj)); + } + return perm_obj; +} + +jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst, uint16_t permissions) { struct obj_link *linkval = obj_deref(dst); linkval->obj = *tgt; linkval->refcount = 2; + linkval->permissions = permissions; { jove_owned_obj_t *tgt_owned = obj_take(tgt); diff --git a/sys/link.h b/sys/link.h index 37fa1e8..3f7331f 100644 --- a/sys/link.h +++ b/sys/link.h @@ -1,3 +1,4 @@ +#include "sys/lockstack.h" #ifndef _JOVE_SYS_LINK_HPP #define _JOVE_SYS_LINK_HPP 1 @@ -5,17 +6,28 @@ struct obj_link { - size_t refcount; jove_obj_t obj; + uint16_t refcount; + uint8_t permissions; }; -void *obj_deref_linked(jove_owned_obj_t *obj); -uint8_t obj_gettype_linked(jove_owned_obj_t *obj); -uint64_t obj_getvalue_linked(jove_owned_obj_t *obj); +typedef struct obj_perm_group +{ + jove_owned_obj_t *obj; + uint8_t permissions; +} jove_perm_obj_t; + +uint8_t link_gettype(jove_owned_obj_t *obj); +uint8_t link_getperm(jove_owned_obj_t *link); +uint64_t link_getvalue(jove_owned_obj_t *obj); jove_owned_obj_t *link_deref(jove_owned_obj_t *link); -jove_obj_t link_unlink(jove_owned_obj_t *link); +jove_owned_obj_t *link_try_deref(jove_owned_obj_t *link); -jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst); +jove_perm_obj_t link_traverse(jove_owned_obj_t *link, lockstack_t *lockstack); +jove_perm_obj_t link_try_traverse(jove_owned_obj_t *link, lockstack_t *lockstack); + +jove_obj_t link_unlink(jove_owned_obj_t *link); +jove_owned_obj_t *link_new(jove_obj_t *tgt, jove_owned_obj_t *dst, uint16_t permissions); #endif diff --git a/sys/lockstack.c b/sys/lockstack.c new file mode 100644 index 0000000..7a419ac --- /dev/null +++ b/sys/lockstack.c @@ -0,0 +1,30 @@ +#include "lockstack.h" +#include "lib/printf.h" + +jove_owned_obj_t* +lockstack_push(lockstack_t *stack, jove_owned_obj_t *obj) +{ + if(stack->depth == LOCKSTACK_MAX) { + klogf("lock stack exceeds %i entries\n", LOCKSTACK_MAX); + return NULL; + } + if(obj == NULL) return obj; + + stack->stack[stack->depth++] = obj; + return obj; +} + +jove_obj_t* +lockstack_pop(lockstack_t *stack) +{ + return obj_release(stack->stack[--stack->depth]); +} + +void +lockstack_popall(lockstack_t *stack) +{ + for(size_t i = 0; i < stack->depth; i++) + obj_release(stack->stack[i]); + stack->depth = 0; +} + diff --git a/sys/lockstack.h b/sys/lockstack.h new file mode 100644 index 0000000..f41f9dc --- /dev/null +++ b/sys/lockstack.h @@ -0,0 +1,18 @@ +#ifndef _JOVE_SYS_LOCKSTACK_H +#define _JOVE_SYS_LOCKSTACK_H 1 + +#include +#include "hal/obj.h" +#include "config.h" + +typedef struct lockstack +{ + size_t depth; + jove_owned_obj_t *stack[LOCKSTACK_MAX]; +} lockstack_t; + +jove_owned_obj_t *lockstack_push(lockstack_t *stack, jove_owned_obj_t *obj); +jove_obj_t *lockstack_pop(lockstack_t *stack); +void lockstack_popall(lockstack_t *stack); + +#endif diff --git a/sys/syscall.c b/sys/syscall.c index 457b820..0da3475 100644 --- a/sys/syscall.c +++ b/sys/syscall.c @@ -24,28 +24,20 @@ int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t payload_bytes, vo } int -_syscall_handle_generic( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload) +_syscall_handle_generic(syscall_context_t *ctx) { - pcb_t *pcb = obj_deref(pcb_obj); - klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), header->path, header->pathlen); - return EBADOBJ; + pcb_t *pcb = obj_deref(ctx->pcb); + klogf("Process %i encountered stub syscall on object %P\n", pcb_pid(pcb), ctx->header->path, ctx->header->pathlen); + return -EBADOBJ; } static const syscall_handle_t s_syscall_handles[128] = { - [JOVE_OBJ_NONE] = NULL, [JOVE_OBJ_UNTYPED] = _syscall_handle_untyped, [JOVE_OBJ_OBJDIR] = _syscall_handle_objdir, [JOVE_OBJ_PAGEDIR] = _syscall_handle_pagedir, [JOVE_OBJ_PROCESSOR] = _syscall_handle_generic, - [JOVE_OBJ_HWMEMORY] = _syscall_handle_generic, - [JOVE_OBJ_PROCESS] = _syscall_handle_generic, + [JOVE_OBJ_SHMEMORY] = _syscall_handle_generic, + [JOVE_OBJ_PCB] = _syscall_handle_generic, [JOVE_OBJ_INT_HANDLE] = _syscall_handle_generic, [JOVE_OBJ_INITRD_FILE] = _syscall_handle_generic, [JOVE_OBJ_FRAMEBUFFER] = _syscall_handle_generic, @@ -54,37 +46,64 @@ static const syscall_handle_t s_syscall_handles[128] = { [JOVE_OBJ_LINK] = _syscall_handle_generic, }; +int +_syscall_handle_switch(syscall_context_t *ctx) +{ + uint8_t target_type = obj_gettype(ctx->target.obj); + if(target_type > 0x7F) { + return _syscall_handle_arch(ctx); + } + else { + syscall_handle_t call_handle = s_syscall_handles[target_type]; + if(call_handle == NULL) { + klogf("Tried to call syscall on object %P which doesn't support syscalls!\n", + ctx->header->path, ctx->header->pathlen); + return -EBADOBJ; + } + else { + return call_handle(ctx); + } + } +} + int syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) { uint16_t *message_path = (uint16_t*)&message_path_raw; if(message_pathlen > sizeof(uintmax_t) >> 1) { - return EBADPATH; + return -EBADPATH; } - jove_owned_obj_t *pcb_obj = process_current(); - pcb_t *pcb = obj_deref(pcb_obj); - jove_owned_obj_t *objdir = pcb_rootdir(pcb); - jove_owned_obj_t *message_obj = objdir_trygetobj(objdir, message_path, message_pathlen); + syscall_context_t ctx; + ctx.lockstack.depth = 0; int sysret = 0; - if(message_obj == NULL) { - klogf("Process %i tried to call syscall with bad message %P : %s\n", + ctx.pcb = lockstack_push(&ctx.lockstack, process_current()); + pcb_t *pcb = obj_deref(ctx.pcb); + ctx.objdir = lockstack_push(&ctx.lockstack, obj_take(pcb_rootdir(pcb))); + + ctx.message = link_try_traverse( + lockstack_push(&ctx.lockstack, objdir_trygetobj( + ctx.objdir, message_path, message_pathlen)), + &ctx.lockstack); + + if(ctx.message.obj == NULL) { + klogf("Process %i failed to get message %P : %s\n", pcb_pid(pcb), message_path, message_pathlen, errstr(errno)); sysret = -errno; - goto release_premsg; + goto release_return; } - if(obj_gettype_linked(message_obj) != JOVE_OBJ_MESSAGE) { + if(obj_gettype(ctx.message.obj) != JOVE_OBJ_MESSAGE) { klogf("Process %i tried to call syscall with invalid object %P\n", pcb_pid(pcb), message_path, message_pathlen); sysret = -EBADOBJ; goto release_return; } - size_t messagelen = message_len(message_obj); - void *messagedata = message_data(message_obj); + size_t messagelen = message_len(ctx.message.obj); + void *messagedata = message_data(ctx.message.obj); struct syscall_header *header = messagedata; size_t bytes_needed = sizeof(struct syscall_header) + header->pathlen * 2; @@ -94,8 +113,14 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) sysret = -ETOOSMALL; goto release_return; } - jove_owned_obj_t *target = objdir_trygetobj(objdir, header->path, header->pathlen); - if(target == 0) { + + ctx.header = header; + ctx.bytes_left = messagelen - bytes_needed; + ctx.payload = (void*)((uintptr_t)header + bytes_needed); + + ctx.target.obj = lockstack_push(&ctx.lockstack, + objdir_trygetobj(ctx.objdir, header->path, header->pathlen)); + if(ctx.target.obj == 0) { //Could not find payload target in pcb rootdir. klogf("Process %i tried to call syscall with bad target path %P : %s\n", pcb_pid(pcb), header->path, header->pathlen, errstr(errno)); @@ -103,28 +128,10 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) goto release_return; } - uint8_t target_type = obj_gettype(target); - size_t bytes_left = messagelen - bytes_needed; - if(target_type > 0x7F) { - sysret = _syscall_handle_arch( - pcb_obj, objdir, message_obj, target, - header, bytes_left, messagedata + bytes_needed); - }else{ - syscall_handle_t call_handle = s_syscall_handles[obj_gettype(target)]; - if(call_handle == NULL) { - klogf("Process %i tried to call syscall on object %P which doesn't support syscalls!\n", - pcb_pid(pcb), header->path, header->pathlen); - sysret = -EBADOBJ; - }else - sysret = call_handle( - pcb_obj, objdir, message_obj, target, - header, bytes_left, messagedata + bytes_needed); - } - obj_release(target); + ctx.target.permissions = JOVE_PERM_ALL; + sysret = _syscall_handle_switch(&ctx); + release_return: - obj_release(message_obj); -release_premsg: - obj_release(objdir); - obj_release(pcb_obj); + lockstack_popall(&ctx.lockstack); return sysret; } diff --git a/sys/syscall.h b/sys/syscall.h index 9f56447..e6358cb 100644 --- a/sys/syscall.h +++ b/sys/syscall.h @@ -1,8 +1,11 @@ #ifndef _JOVE_SYS_SYSCALL_H #define _JOVE_SYS_SYSCALL_H 1 +#include "config.h" #include "api/syscall.h" #include "hal/obj.h" +#include "lockstack.h" +#include "link.h" #include #define CHECK_TOOSMALL(required, present, fail_msg) \ @@ -20,29 +23,39 @@ do { if(obj == NULL) { \ #define CHECK_OBJTYPE(obj, type, fail_msg) \ do { if(obj_gettype(obj) != type) { \ kprintf("%s: %s\n", __func__, fail_msg); \ - obj_release(obj); \ return -EBADOBJ; \ } } while(0) -#define SYSCALL_FUNCTION_ARGS \ - jove_owned_obj_t*, /*PCB object*/ \ - jove_owned_obj_t*, /*Objdir object*/ \ - jove_owned_obj_t*, /*Message object*/ \ - jove_owned_obj_t*, /*Target object*/ \ - struct syscall_header*, /*Syscall header*/ \ - size_t, /*How many bytes are left in the message*/ \ - void* /*The bytes left in the message.*/ +#define CHECK_OBJPERM(obj, perms, fail_msg) \ + do { if((obj.permissions & perms) == 0) { \ + kprintf("%s: %s\n", __func__, fail_msg); \ + return -EPERM; \ + } } while(0) -typedef int (*syscall_handle_t)(SYSCALL_FUNCTION_ARGS); +typedef struct syscall_state +{ + lockstack_t lockstack; + jove_owned_obj_t *pcb; + jove_owned_obj_t *objdir; + jove_perm_obj_t message; + jove_perm_obj_t target; + struct syscall_header *header; + size_t bytes_left; + void *payload; +} syscall_context_t; + +typedef int (*syscall_handle_t)(syscall_context_t*); int __syscall_generic_objpath(jove_owned_obj_t *objdir, size_t bytes_left, void *payload_data, jove_owned_obj_t **retobj); -int _syscall_handle_generic(SYSCALL_FUNCTION_ARGS); -int _syscall_handle_arch(SYSCALL_FUNCTION_ARGS); +int _syscall_handle_switch(syscall_context_t *ctx); + +int _syscall_handle_generic(syscall_context_t *ctx); +int _syscall_handle_arch(syscall_context_t *ctx); -int _syscall_handle_vtt(SYSCALL_FUNCTION_ARGS); -int _syscall_handle_objdir(SYSCALL_FUNCTION_ARGS); -int _syscall_handle_untyped(SYSCALL_FUNCTION_ARGS); -int _syscall_handle_pagedir(SYSCALL_FUNCTION_ARGS); +int _syscall_handle_vtt(syscall_context_t *ctx); +int _syscall_handle_objdir(syscall_context_t *ctx); +int _syscall_handle_untyped(syscall_context_t *ctx); +int _syscall_handle_pagedir(syscall_context_t *ctx); #endif diff --git a/sys/syscall_objdir.c b/sys/syscall_objdir.c index 277639f..5a6786d 100644 --- a/sys/syscall_objdir.c +++ b/sys/syscall_objdir.c @@ -25,20 +25,15 @@ s_syscall_objdir_objtype( } int -_syscall_handle_objdir( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload) +_syscall_handle_objdir(syscall_context_t *ctx) { - switch(header->callid) { + switch(ctx->header->callid) { case SYSCALL_OBJDIR_OBJTYPE: - return s_syscall_objdir_objtype(objdir, target_obj, bytes_left, payload); + if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_OBJTYPE) + return s_syscall_objdir_objtype( + ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload); + return -EPERM; default: - kprintf("syscall_handle_objdir: Objdir does not support syscall %i\n", header->callid); - return EBADARG; + return -EBADCALL; } } diff --git a/sys/syscall_pagedir.c b/sys/syscall_pagedir.c index 33acc87..961c477 100644 --- a/sys/syscall_pagedir.c +++ b/sys/syscall_pagedir.c @@ -5,12 +5,13 @@ #include "syscall.h" static int -s_syscall_pagedir_map( +s_get_untyped( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pml4, size_t payload_bytes, void *payload_data, - jove_owned_obj_t **untyped_ret) + jove_perm_obj_t *untyped_ret) { size_t bytes_needed = sizeof(struct syscall_pagedir_map); CHECK_TOOSMALL(bytes_needed, payload_bytes, @@ -27,40 +28,44 @@ s_syscall_pagedir_map( "Message too small for untyped path."); errno = 0; - jove_owned_obj_t *untyped_obj = objdir_trygetobj(objdir, - payload->untyped_path, payload->untyped_pathlen); + jove_perm_obj_t untyped = link_try_traverse( + lockstack_push(lockstack, objdir_trygetobj( + objdir, payload->untyped_path, payload->untyped_pathlen)), + lockstack); if(errno) { kprintf("%s: Untyped obj failed for the reason: %s\n", __func__, errstr(errno)); return errno; } - CHECK_OBJTYPE(untyped_obj, JOVE_OBJ_UNTYPED, + CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Untyped path does not point to an untyped object."); - jove_untyped_t *untyped_data = obj_deref(untyped_obj); + CHECK_OBJPERM(untyped, JOVE_PERM_MUTATE, + "Untyped object does not have MUTATE permission."); + + jove_untyped_t *untyped_data = obj_deref(untyped.obj); if((uintptr_t)untyped_data & 0xFFF) { kprintf("%s: Untyped object is not page aligned.\n", __func__); - obj_release(untyped_obj); return EALIGN; } if(untyped_data->limit != 0x1000) { kprintf("%s: Untyped object is not page sized. (expected 0x1000 got 0x%X)\n", __func__, untyped_data->limit); - obj_release(untyped_obj); return EBADSIZE; } - *untyped_ret = untyped_obj; + *untyped_ret = untyped; return 0; } static int s_syscall_pagedir_unmap( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pagedir, size_t payload_bytes, void *payload_data, - jove_owned_obj_t **none_ret) + jove_perm_obj_t *none_ret) { size_t bytes_needed = sizeof(struct syscall_pagedir_unmap); CHECK_TOOSMALL(bytes_needed, payload_bytes, @@ -76,117 +81,186 @@ s_syscall_pagedir_unmap( CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message too small for none path"); - jove_owned_obj_t *none_obj = objdir_trygetobj(objdir, - payload->none_path, payload->none_pathlen); + jove_perm_obj_t none = link_try_traverse( + lockstack_push(lockstack, objdir_trygetobj( + objdir, payload->none_path, payload->none_pathlen)), + lockstack); if(errno) { kprintf("%s: None obj retrieval failed for the reason: %s\n", __func__, errstr(errno)); return errno; } - CHECK_OBJTYPE(none_obj, JOVE_OBJ_NONE, + CHECK_OBJTYPE(none.obj, JOVE_OBJ_NONE, "None path does not point to none object."); - *none_ret = none_obj; + *none_ret = none; return 0; } static int s_syscall_pagedir_map_frame( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pagedir, size_t payload_bytes, void *payload_data) { - jove_owned_obj_t *untyped_obj = NULL; - int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj); + jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 }; + int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped); if(sysret != 0) { return sysret; } struct syscall_pagedir_map *payload = payload_data; - sysret = pagedir_map_untyped_frame(target_obj, untyped_obj, payload->virtual_address, payload->flags); + sysret = pagedir_map_untyped_frame(pagedir, &untyped, payload->virtual_address, payload->page_flags); if(sysret == 0) - obj_settype(untyped_obj, JOVE_OBJ_NONE); + obj_settype(untyped.obj, JOVE_OBJ_NONE); - obj_release(untyped_obj); return sysret; } static int s_syscall_pagedir_map_table( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pagedir, size_t payload_bytes, void *payload_data) { - jove_owned_obj_t *untyped_obj = NULL; - int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj); + jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 }; + int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped); if(sysret != 0) { return sysret; } struct syscall_pagedir_map *payload = payload_data; - sysret = pagedir_map_untyped_table(target_obj, untyped_obj, payload->virtual_address); + sysret = pagedir_map_untyped_table(pagedir, &untyped, payload->virtual_address); if(sysret == 0) - obj_settype(untyped_obj, JOVE_OBJ_NONE); + obj_settype(untyped.obj, JOVE_OBJ_NONE); - obj_release(untyped_obj); return sysret; } +static int +s_syscall_pagedir_map_shmem( + lockstack_t *lockstack, + jove_owned_obj_t *objdir, + jove_owned_obj_t *pagedir, + size_t payload_bytes, + void *payload_data) +{ + size_t bytes_needed = sizeof(struct syscall_pagedir_map_shmem); + CHECK_TOOSMALL(bytes_needed, payload_bytes, + "Message too small for payload."); + + struct syscall_pagedir_map_shmem *payload = payload_data; + if(payload->virtual_address > 0xFFFF800000000000ULL) { + kprintf("%s: Virtual address is above user limit.\n", __func__); + return EBADARG; + } + + bytes_needed += payload->shmem_pathlen << 1; + CHECK_TOOSMALL(bytes_needed, payload_bytes, + "Message too small for untyped path."); + + errno = 0; + jove_perm_obj_t shmem = link_try_traverse( + lockstack_push(lockstack, objdir_trygetobj( + objdir, payload->shmem_path, payload->shmem_pathlen)), + lockstack); + if(errno) { + klogf("Shared memory obj failed for the reason: %s\n", errstr(errno)); + return errno; + } + + CHECK_OBJTYPE(shmem.obj, JOVE_OBJ_SHMEMORY, + "Shared memory path does not point to a shared memory object."); + + uintmax_t shmem_value = obj_getvalue(shmem.obj); + uint8_t shmem_pages = shmem_value & 0xFF; + + if(payload->page_offset >= shmem_pages) { + klogf("Page offset goes beyond size of shared memory object: (%i >= %i)\n", + payload->page_offset, shmem_pages); + return -EOOB; + } + + return pagedir_map_shmem_frame(pagedir, &shmem, payload->page_offset, + payload->virtual_address, payload->page_flags); +} + static int s_syscall_pagedir_unmap_frame( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pagedir, size_t payload_bytes, void *payload_data) { - jove_owned_obj_t *none_obj; - int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj); + jove_perm_obj_t none; + int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none); if(!sysret) return sysret; struct syscall_pagedir_unmap *payload = payload_data; - return pagedir_unmap_untyped_frame(target_obj, none_obj, payload->virtual_address); + return pagedir_unmap_untyped_frame(pagedir, none.obj, payload->virtual_address); } static int s_syscall_pagedir_unmap_table( + lockstack_t *lockstack, jove_owned_obj_t *objdir, - jove_owned_obj_t *target_obj, + jove_owned_obj_t *pagedir, size_t payload_bytes, void *payload_data) { - jove_owned_obj_t *none_obj; - int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj); + jove_perm_obj_t none; + int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none); if(!sysret) return sysret; struct syscall_pagedir_unmap *payload = payload_data; - return pagedir_unmap_untyped_table(target_obj, none_obj, payload->virtual_address); + return pagedir_unmap_untyped_table(pagedir, none.obj, payload->virtual_address); } int -_syscall_handle_pagedir( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload) +_syscall_handle_pagedir(syscall_context_t *ctx) { + lockstack_t *lockstack = &ctx->lockstack; + struct syscall_header *header = ctx->header; + jove_owned_obj_t *objdir = ctx->objdir; + jove_perm_obj_t *target = &ctx->target; + size_t bytes_left = ctx->bytes_left; + void *payload = ctx->payload; + switch(header->callid) { case SYSCALL_PAGEDIR_MAP_FRAME: - return s_syscall_pagedir_map_frame(objdir, target_obj, bytes_left, payload); + if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_FRAME) + return s_syscall_pagedir_map_frame(lockstack, objdir, target->obj, bytes_left, payload); + return -EPERM; + case SYSCALL_PAGEDIR_MAP_TABLE: - return s_syscall_pagedir_map_table(objdir, target_obj, bytes_left, payload); + if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_TABLE) + return s_syscall_pagedir_map_table(lockstack, objdir, target->obj, bytes_left, payload); + return -EPERM; + + case SYSCALL_PAGEDIR_MAP_SHMEM: + if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_SHMEM) + return s_syscall_pagedir_map_shmem(lockstack, objdir, target->obj, bytes_left, payload); + return -EPERM; + case SYSCALL_PAGEDIR_UNMAP_FRAME: - return s_syscall_pagedir_unmap_frame(objdir, target_obj, bytes_left, payload); + if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_FRAME) + return s_syscall_pagedir_unmap_frame(lockstack, objdir, target->obj, bytes_left, payload); + return -EPERM; + case SYSCALL_PAGEDIR_UNMAP_TABLE: - return s_syscall_pagedir_unmap_table(objdir, target_obj, bytes_left, payload); + if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_TABLE) + return s_syscall_pagedir_unmap_table(lockstack, objdir, target->obj, bytes_left, payload); + return -EPERM; + default: kprintf("syscall_handle_pagedir: Pagedir does not support syscall %i\n", header->callid); return EBADARG; diff --git a/sys/syscall_untyped.c b/sys/syscall_untyped.c index a5659a6..a117387 100644 --- a/sys/syscall_untyped.c +++ b/sys/syscall_untyped.c @@ -6,6 +6,7 @@ static int s_syscall_untyped_split( + lockstack_t *lockstack, jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, @@ -18,19 +19,24 @@ s_syscall_untyped_split( bytes_needed += payload->dest_pathlen * 2; CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for destination path!"); - jove_owned_obj_t *dst_obj = objdir_getobj(objdir, payload->dest_path, payload->dest_pathlen); - CHECK_OBJTYPE(dst_obj, JOVE_OBJ_NONE, "Destination path is occupied!"); + jove_perm_obj_t dest = link_try_traverse( + lockstack_push(lockstack, + objdir_trygetobj(objdir, payload->dest_path, payload->dest_pathlen)), + lockstack); + + CHECK_OBJTYPE(dest.obj, JOVE_OBJ_NONE, "Destination path is occupied!"); if(payload->bytes < JOVE_UNTYPED_MINSIZE) { klogf("Destination untyped would be too small. (%X < %X)\n", payload->bytes, JOVE_UNTYPED_MINSIZE); - return EBADARG; + return -ETOOBIG; } - return untyped_split(target_obj, dst_obj, payload->bytes); + return untyped_split(target_obj, dest.obj, payload->bytes); } static int s_syscall_untyped_merge( + lockstack_t *lockstack, jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, @@ -43,41 +49,51 @@ s_syscall_untyped_merge( bytes_needed += payload->pathlen * 2; CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for second path!"); - jove_owned_obj_t *snd_obj = objdir_getobj(objdir, payload->path, payload->pathlen); - CHECK_OBJTYPE(snd_obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!"); + jove_perm_obj_t untyped = link_try_traverse( + lockstack_push(lockstack, + objdir_getobj(objdir, payload->path, payload->pathlen)), + lockstack); + CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!"); + CHECK_OBJPERM(untyped, SYSCALL_PERM_UNTYPED_MERGE, "Second untyped does not have permission to merge!"); - int sysret = untyped_merge(target_obj, snd_obj); - if(obj_gettype(snd_obj) == JOVE_OBJ_UNTYPED) { + int sysret = untyped_merge(target_obj, untyped.obj); + if(obj_gettype(untyped.obj) == JOVE_OBJ_UNTYPED) { //Untyped merged into second object. We need to switch objects. obj_settype(target_obj, JOVE_OBJ_UNTYPED); - obj_setvalue(target_obj, obj_getvalue(snd_obj)); - obj_settype(snd_obj, JOVE_OBJ_NONE); + obj_setvalue(target_obj, obj_getvalue(untyped.obj)); + obj_settype(untyped.obj, JOVE_OBJ_NONE); } return sysret; } -int _syscall_handle_untyped( - jove_owned_obj_t* pcb_obj, - jove_owned_obj_t* objdir, - jove_owned_obj_t* message_obj, - jove_owned_obj_t* target_obj, - struct syscall_header* header, - size_t payload_bytes, - void* payload) +int _syscall_handle_untyped(syscall_context_t *ctx) { - switch(header->callid) { - case SYSCALL_UNTYPED_ADDRESS: - return untyped_address(target_obj); + switch(ctx->header->callid) { + case SYSCALL_UNTYPED_ADDRESS: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_ADDRESS) + return untyped_address(ctx->target.obj); + return -EPERM; + case SYSCALL_UNTYPED_SIZE: - return untyped_size(target_obj); + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SIZE) + return untyped_size(ctx->target.obj); + return -EPERM; + case SYSCALL_UNTYPED_SPLIT: - return s_syscall_untyped_split(objdir, target_obj, payload_bytes, payload); + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SPLIT) + return s_syscall_untyped_split( + &ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload); + return -EPERM; + case SYSCALL_UNTYPED_MERGE: - return s_syscall_untyped_merge(objdir, target_obj, payload_bytes, payload); + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_MERGE) + return s_syscall_untyped_merge( + &ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload); + return -EPERM; + default: - kprintf("syscall_untyped: Untyped object does not support syscall %i\n", header->callid); - return -EBADARG; + return -EBADCALL; } return 0; } diff --git a/sys/syscall_vtt.c b/sys/syscall_vtt.c index 4dadd6c..dad05ba 100644 --- a/sys/syscall_vtt.c +++ b/sys/syscall_vtt.c @@ -20,20 +20,14 @@ s_syscall_vtt_write( } int -_syscall_handle_vtt( - jove_owned_obj_t *pcb_obj, - jove_owned_obj_t *objdir, - jove_owned_obj_t *message_obj, - jove_owned_obj_t *target_obj, - struct syscall_header *header, - size_t bytes_left, - void *payload_data) +_syscall_handle_vtt(syscall_context_t *ctx) { - switch(header->callid) { - case 0: - return s_syscall_vtt_write(target_obj, bytes_left, payload_data); + + switch(ctx->header->callid) { + case SYSCALL_VTT_WRITE: + return s_syscall_vtt_write(ctx->target.obj, ctx->bytes_left, ctx->payload); default: - kprintf("syscall_vtt: vtt object does not support syscall %i\n", header->callid); - return EOOB; + klogf("vtt object does not support syscall %i\n", ctx->header->callid); + return -EBADCALL; } } -- cgit v1.2.3