#include "arch/x86_64/hal/obj.h" #include "hal/memory.h" #include "jove.h" #include "lib/printf.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 _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; default: return -EBADCALL; } return 0; }