#include "arch/x86_64/hal/obj.h" #include "proc/process.h" #include "jove.h" #include "lib/printf.h" #include "sys/objdir.h" #include "syscall.h" int s_syscall_objdir_objtype( jove_obj_t *objdir, jove_obj_t *target_dir, size_t payload_size, void *payload_data) { size_t bytes_needed = 2; CHECK_TOOSMALL(bytes_needed, payload_size, "Message is too small for payload."); uint16_t local_idx = *((uint16_t*)payload_data); if(local_idx > OBJDIR_ENTRIES) { kprintf("%s: Object index is out of bounds (%i >= 512)\n", __func__, local_idx); return EOOB; } jove_obj_t local_obj = objdir_peeklocal(target_dir, local_idx); return obj_peektype(local_obj); } static int s_syscall_objdir_swap(lockstack_t *lockstack, jove_obj_t *rootdir, size_t bytes_left, void *payload_data) { //Verify the message is big enough for the payload. size_t bytes_needed = sizeof(struct syscall_objdir_swap); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload."); //Verify the message is big enough for the other path. struct syscall_objdir_swap *payload = payload_data; bytes_needed += payload->other_path_length * sizeof(objpath_part_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for other path."); //Verify the object pointed to in the entry exists. jove_obj_t *target = lockstack_pop(lockstack); jove_owned_obj_t *obj_a = lockstack_push(lockstack, objdir_getlocal(target, payload->index)); if(obj_a == NULL) { klogf("Getting local object %i failed : %s\n", payload->index, errstr(errno)); return -errno; } //Verify the second object directory exists. jove_perm_obj_t objdir_b = link_traverse_objdir(rootdir, payload->other_path_length - 1, payload->other_path); if(objdir_b.obj == NULL) { obj_release(objdir_b.obj); klogf("Getting object %P failed : %s\n", payload->other_path, payload->other_path_length, errstr(errno)); return -errno; } //Verify the second object directory has the correct permissions. CHECK_OBJPERM(objdir_b, SYSCALL_PERM_OBJDIR_SWAP_TGT, "Other object is missing permission"); //Verify the second object exists. jove_owned_obj_t *obj_b = lockstack_push(lockstack, objdir_getlocal_locked(objdir_b.obj, payload->other_path[payload->other_path_length-1])); if(obj_b == NULL) { klogf("Getting object %P failed : %s\n", payload->other_path, payload->other_path_length, errstr(errno)); return -errno; } objdir_swapobj(obj_a, obj_b); return 0; } static int s_syscall_objdir_link(jove_owned_obj_t *target_obj, lockstack_t *lockstack, jove_obj_t *rootdir_obj, size_t bytes_left, void *payload_data) { //Verify the message is big enough for the payload. size_t bytes_needed = sizeof(struct syscall_objdir_link); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); //Verify the message is big enough for the second path. struct syscall_objdir_link *payload = payload_data; bytes_needed += payload->other_path_length * sizeof(objpath_part_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for other object"); //Verify the objdir index is a valid object. jove_owned_obj_t *link_obj = lockstack_push(lockstack, objdir_getlocal_locked(target_obj, payload->index)); if(link_obj == NULL) { klogf("Getting local object %i failed : %s\n", payload->index, errstr(errno)); return -errno; } //Verify that the link object is infact a link object. CHECK_OBJTYPE(link_obj, JOVE_OBJ_LINK, "Local object is not a link object"); jove_perm_obj_t dest_obj = link_traverse_objdir(rootdir_obj, payload->other_path_length, payload->other_path); lockstack_push(lockstack, dest_obj.obj); //Verify the destination path exists. if(dest_obj.obj == NULL) { klogf("Getting destination object %P failed : %s\n", payload->other_path, payload->other_path_length, errstr(errno)); return -errno; } //Verify the destination path is empty. if(obj_gettype(dest_obj.obj) != JOVE_OBJ_NONE) { klogf("Destination object %P is not empty\n", payload->other_path, payload->other_path_length); return -EFULL; } //Verify the destination path has the correct permissions. CHECK_OBJPERM(dest_obj, SYSCALL_PERM_OBJDIR_LINK_TGT, "Destination object is missing permissions"); return link_dup(link_obj, dest_obj.obj); } int _syscall_handle_objdir(syscall_context_t *ctx) { switch(ctx->header->callid) { case SYSCALL_OBJDIR_OBJTYPE: if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_OBJTYPE) return s_syscall_objdir_objtype( ctx->objdir, lockstack_pop(&ctx->lockstack), ctx->bytes_left, ctx->payload); return -EPERM; case SYSCALL_OBJDIR_SWAP: if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_SWAP) return s_syscall_objdir_swap( &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); return -EPERM; case SYSCALL_OBJDIR_LINK: if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_LINK) return s_syscall_objdir_link(ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); return -EPERM; default: return -EBADCALL; } }