diff options
Diffstat (limited to 'sys/syscall_pagedir.c')
| -rw-r--r-- | sys/syscall_pagedir.c | 170 |
1 files changed, 122 insertions, 48 deletions
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; |
