#include "arch/x86_64/hal/obj.h" #include "hal/memory.h" #include "jove.h" #include "lib/printf.h" #include "proc/process.h" #include "syscall.h" static int s_syscall_untyped_split( lockstack_t *lockstack, jove_owned_obj_t *objdir, jove_owned_obj_t *target_obj, size_t payload_bytes, void *payload_data) { int bytes_needed = sizeof(struct syscall_untyped_split); CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for payload!"); struct syscall_untyped_split *payload = payload_data; bytes_needed += payload->dest_pathlen * 2; CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for destination path!"); jove_perm_obj_t dest = link_try_traverse_objdir( objdir, lockstack, payload->dest_pathlen, payload->dest_path); if(errno) { klogf("Unable to get destination object %P: %s\n", payload->dest_path, payload->dest_pathlen, errstr(errno)); return errno; } 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 -ETOOBIG; } 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, void *payload_data) { int bytes_needed = sizeof(struct syscall_generic_objpath); CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for payload!"); struct syscall_generic_objpath *payload = payload_data; bytes_needed += payload->pathlen * 2; CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for second path!"); jove_perm_obj_t untyped = link_try_traverse_objdir( objdir, lockstack, payload->pathlen, payload->path); if(errno) { klogf("Unable to retrieve untyped object %P : %s\n", payload->path, payload->pathlen, errstr(errno)); return errno; } 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, 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(untyped.obj)); obj_settype(untyped.obj, JOVE_OBJ_NONE); } return sysret; } int s_syscall_untyped_retype_pcb(jove_owned_obj_t *untyped_obj, lockstack_t *lockstack, jove_owned_obj_t *rootdir, struct syscall_header *header) { jove_untyped_t *untyped = obj_deref(untyped_obj); CHECK_TOOSMALL(PCB_MINSIZE, untyped->limit, "Untyped object too small for PCB"); jove_perm_obj_t objdir_obj = link_try_traverse_objdir( rootdir, lockstack, header->pathlen - 1, header->path); if(errno) { klogf("Unable to retrieve parent objdir at %P\n", header->path, header->pathlen - 1); return -errno; } CHECK_OBJPERM(objdir_obj, JOVE_PERM_ALL, "New PCB needs full access to it's root objdir!"); obj_settype(untyped_obj, JOVE_OBJ_PCB); return pcb_new(untyped_obj, untyped->limit, objdir_obj.obj); } int _syscall_handle_untyped(syscall_context_t *ctx) { 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: if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SIZE) return untyped_size(ctx->target.obj); return -EPERM; case SYSCALL_UNTYPED_SPLIT: 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: 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; case SYSCALL_UNTYPED_RETYPE_OBJDIR: if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) return objdir_new(ctx->target.obj); return -EPERM; case SYSCALL_UNTYPED_RETYPE_PAGEDIR: if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) return pagedir_new(ctx->target.obj); return -EPERM; case SYSCALL_UNTYPED_RETYPE_SHMEMORY: if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) return shmem_new(ctx->target.obj); return -EPERM; case SYSCALL_UNTYPED_RETYPE_PCB: if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) return s_syscall_untyped_retype_pcb( ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->header); return -EPERM; default: return -EBADCALL; } return 0; }