diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/link.c | 58 | ||||
| -rw-r--r-- | sys/link.h | 24 | ||||
| -rw-r--r-- | sys/message.c | 96 | ||||
| -rw-r--r-- | sys/message.h | 13 | ||||
| -rw-r--r-- | sys/objdir.c | 13 | ||||
| -rw-r--r-- | sys/syscall.c | 8 | ||||
| -rw-r--r-- | sys/syscall_objdir.c | 95 | ||||
| -rw-r--r-- | sys/syscall_pcb.c | 172 | ||||
| -rw-r--r-- | sys/syscall_untyped.c | 5 |
9 files changed, 377 insertions, 107 deletions
@@ -5,46 +5,15 @@ #include "lib/printf.h" #include "jove.h" -uint8_t -link_gettype(jove_owned_obj_t *obj) -{ - return obj_gettype(link_deref(obj)); -} - -uint8_t -link_getperm(jove_owned_obj_t *link) -{ - struct obj_link *linkval = obj_deref(link); - return linkval->permissions; -} - -uint64_t -link_getvalue(jove_owned_obj_t *obj) -{ - return obj_getvalue(link_deref(obj)); -} - -jove_owned_obj_t* -link_deref(jove_owned_obj_t *link) -{ - struct obj_link *linkval = obj_deref(link); - return obj_take(&linkval->obj); -} - -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)); + jove_link_obj_t *link = obj_deref(perm_obj.obj); + perm_obj.permissions &= link_getperm(link); + perm_obj.obj = lockstack_push(lockstack, link_deref(link)); } return perm_obj; } @@ -54,8 +23,9 @@ 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)); + jove_link_obj_t *link = obj_deref(perm_obj.obj); + perm_obj.permissions &= link_getperm(link); + perm_obj.obj = lockstack_push(lockstack, link_deref(link)); } return perm_obj; } @@ -80,19 +50,3 @@ link_try_traverse_objdir(jove_owned_obj_t *objdir, lockstack_t *lockstack, traverse_obj.permissions &= perm_obj.permissions; return traverse_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); - obj_settype(tgt_owned, JOVE_OBJ_LINK); - obj_setvalue(tgt_owned, (uintptr_t)linkval); - obj_release(tgt_owned); - } - return dst; -} @@ -4,12 +4,9 @@ #include "hal/obj.h" -struct obj_link -{ - jove_obj_t obj; - uint16_t refcount; - uint8_t permissions; -}; +#ifdef __x86_64__ +#include "arch/x86_64/sys/link.h" +#endif typedef struct obj_perm_group { @@ -17,12 +14,14 @@ typedef struct obj_perm_group 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); +uint8_t link_getperm(jove_link_obj_t *link); +void link_setperm(jove_link_obj_t *link, uint8_t perm); + +void link_lock(jove_link_obj_t *link); +void link_unlock(jove_link_obj_t *link); -jove_owned_obj_t *link_deref(jove_owned_obj_t *link); -jove_owned_obj_t *link_try_deref(jove_owned_obj_t *link); +jove_owned_obj_t *link_deref(jove_link_obj_t *link); +jove_owned_obj_t *link_try_deref(jove_link_obj_t *link); 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); @@ -34,6 +33,7 @@ jove_perm_obj_t link_try_traverse_objdir(jove_owned_obj_t *objdir, lockstack_t *lockstack, size_t pathlen, objpath_part_t *path); 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); +int link_new(jove_owned_obj_t *target_obj, jove_owned_obj_t *untyped_obj, uint8_t permissions); +int link_dup(jove_owned_obj_t *link_obj, jove_owned_obj_t *dest_obj); #endif diff --git a/sys/message.c b/sys/message.c index c87487b..c4414e0 100644 --- a/sys/message.c +++ b/sys/message.c @@ -1,54 +1,94 @@ #include "message.h" #include "api/error.h" -#include "errno.h" +#include "jove.h" #include "hal/memory.h" #include "hal/obj.h" #include "lib/printf.h" -int -message_hasmap(jove_owned_obj_t *obj) +static inline uintptr_t +s_message_addr(jove_owned_obj_t *message_obj) +{ + return (obj_getvalue(message_obj) >> 1) << 12; +} + +int message_new(jove_owned_obj_t *untyped_obj) +{ + uintmax_t untyped_value = obj_getvalue(untyped_obj); + jove_untyped_t *untyped = obj_deref(untyped_obj); + if(untyped->limit != 0x1000) { + klogf("Passed untyped has bad size : %x vs %x\n", untyped->limit, MESSAGE_SIZE); + return -EBADSIZE; + } + if(untyped_value & (MESSAGE_ALIGN - 1)) { + klogf("Passed untyped has bad alignment : %x\n", untyped_value & (MESSAGE_ALIGN - 1)); + return -EALIGN; + } + + obj_settype(untyped_obj, JOVE_OBJ_MESSAGE); + obj_setvalue(untyped_obj, obj_getvalue(untyped_obj) >> 11); + return 0; +} + +inline int +message_hasmap(jove_owned_obj_t *message_obj) { - return obj_getvalue(obj) & 1; + return obj_getvalue(message_obj) & 1; } -uintptr_t -message_unmap(jove_owned_obj_t *obj, jove_owned_obj_t *pagedir) +virtaddr_t +message_unmap(jove_owned_obj_t *message_obj, jove_owned_obj_t *pagedir_obj) { - if(message_hasmap(obj) == 0) { - kprintf("Message %p doesn't have a map\n", obj_getvalue(obj)); - return -ENOMAP; + errno = 0; + if(message_hasmap(message_obj) == 0) { + klogf("Message %p doesn't have a map\n", obj_getvalue(message_obj)); + errno = -ENOMAP; + return 0; } - uintptr_t vptr = obj->locked.value & ~0xFFFULL; - uintptr_t *mapping = pagedir_get_mapping(pagedir, vptr); + + virtaddr_t message_vaddr = s_message_addr(message_obj); + virtaddr_t *mapping = pagedir_get_mapping(pagedir_obj, message_vaddr); + physaddr_t message_pfn = pagedir_mapping_get_pfn(mapping); pagedir_mapping_set_present(mapping, false); - pagedir_invlpg(vptr); + obj_setvalue(message_obj, message_pfn << 1); + pagedir_invlpg(message_vaddr); + message_klogf("Unmapped message %p from %p\n", message_pfn << 12, message_vaddr); - obj_setvalue(obj, *mapping); - return vptr; + return message_vaddr; } -void -message_remap(jove_owned_obj_t *message, jove_owned_obj_t *pagedir, uintptr_t vptr) +int +message_map(jove_owned_obj_t *message, jove_owned_obj_t *pagedir, virtaddr_t vaddr) { if(message_hasmap(message)) { - errno = -EHASMAP; - return; + return -EHASMAP; } - uintmax_t *mapping = pagedir_get_mapping(pagedir, vptr); + virtaddr_t message_paddr = s_message_addr(message); + virtaddr_t *mapping = pagedir_get_mapping(pagedir, vaddr); - *mapping = obj_getvalue(message) | 1; - pagedir_invlpg(vptr); + if(pagedir_mapping_is_present(mapping)) { + klogf("Mapping %p is occupied\n", + mapping, message); + return -EHASMAP; + } + + pagedir_mapping_set_pfn(mapping, message_paddr >> 12); + pagedir_mapping_set_present(mapping, true); + pagedir_mapping_set_writeable(mapping, true); + pagedir_mapping_set_user(mapping, true); + pagedir_mapping_set_type(mapping, JOVE_MAPPING_TYPE_MESSAGE); - obj_setvalue(message, vptr | 1); + pagedir_invlpg(vaddr); + + message_klogf("Mapped message %p to %p\n", message_paddr, vaddr); + obj_setvalue(message, (vaddr >> 11) | 1); + return 0; } -uintptr_t message_getdata(jove_owned_obj_t *message) +virtaddr_t message_getdata(jove_owned_obj_t *message) { - if(message_hasmap(message)) - return obj_getvalue(message) & ~0xFFFULL; - - uintptr_t message_val = obj_getvalue(message); - return pagedir_ident_from_mapping(&message_val); + uintptr_t message_addr = s_message_addr(message); + if(message_hasmap(message)) return message_addr; + return (virtaddr_t)phys_tovirt(message_addr); } diff --git a/sys/message.h b/sys/message.h index 97d0f71..1a3b43e 100644 --- a/sys/message.h +++ b/sys/message.h @@ -2,13 +2,20 @@ #define _JOVE_SYS_MESSAGE_H 1 #include "hal/obj.h" +#include "hal/memory.h" +#ifdef DEBUG_MESSAGE +#include "lib/printf.h" +#define message_klogf(fmt, ...) kprintf("%s: " fmt, __func__, __VA_ARGS__) +#else +#define message_klogf(fmt, ...) +#endif -#define MESSAGE_ALIGN 0x1000 +int message_new(jove_owned_obj_t *untyped_obj); int message_hasmap(jove_owned_obj_t *message); -uintptr_t message_unmap(jove_owned_obj_t *message, jove_owned_obj_t *pagedir); -void message_remap(jove_owned_obj_t *message, jove_owned_obj_t *pagedir, uintptr_t vptr); +virtaddr_t message_unmap(jove_owned_obj_t *message, jove_owned_obj_t *pagedir); +int message_map(jove_owned_obj_t *message, jove_owned_obj_t *pagedir, virtaddr_t vaddr); uintptr_t message_getdata(jove_owned_obj_t *message); diff --git a/sys/objdir.c b/sys/objdir.c index f956309..5b59ddc 100644 --- a/sys/objdir.c +++ b/sys/objdir.c @@ -4,16 +4,15 @@ #include "hal/obj.h" #include "lib/string.h" #include "jove.h" -#include <errno.h> int objdir_new(jove_owned_obj_t *untyped_obj) { jove_untyped_t *untyped = obj_deref(untyped_obj); - if((uintptr_t)untyped & (JOVE_OBJDIR_SIZE - 1)) return -EALIGN; - if(untyped->limit != JOVE_OBJDIR_SIZE) return -EBADSIZE; + if((uintptr_t)untyped & (OBJDIR_SIZE - 1)) return -EALIGN; + if(untyped->limit != OBJDIR_SIZE) return -EBADSIZE; - memset(untyped, 0, JOVE_OBJDIR_SIZE); + memset(untyped, 0, OBJDIR_SIZE); obj_settype(untyped_obj, JOVE_OBJ_OBJDIR); return 0; } @@ -27,7 +26,7 @@ objdir_peeklocal( errno = EBADOBJ; return (jove_obj_t) { 0 }; } - if(entry >= JOVE_OBJDIR_ENTRIES) { + if(entry >= OBJDIR_ENTRIES) { errno = EBADPATH; return (jove_obj_t) { 0 }; } @@ -44,7 +43,7 @@ objdir_getlocal( if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { reterr(EBADOBJ); } - if(entry >= JOVE_OBJDIR_ENTRIES) { + if(entry >= OBJDIR_ENTRIES) { reterr(EBADPATH); } @@ -60,7 +59,7 @@ objdir_trygetlocal( if(obj_gettype(objdir_obj) != JOVE_OBJ_OBJDIR) { reterr(EBADOBJ); } - if(entry >= JOVE_OBJDIR_ENTRIES) { + if(entry >= OBJDIR_ENTRIES) { reterr(EBADPATH); } diff --git a/sys/syscall.c b/sys/syscall.c index 0c40418..7d43d66 100644 --- a/sys/syscall.c +++ b/sys/syscall.c @@ -116,6 +116,12 @@ syscall_handler(uintmax_t message_path_raw, uint16_t message_pathlen) jove_owned_obj_t *pagedir = lockstack_push(&ctx.lockstack, pcb_getpagedir(ctx.objdir)); uintptr_t message_vptr = message_unmap(ctx.message.obj, pagedir); + if(message_vptr == 0) { + klogf("Process %i tried to call syscall with unmapped message %P\n", + pcb_getpid(pcb), message_path, message_pathlen); + sysret = -EBADOBJ; + goto release_return; + } size_t messagelen = 0x1000; void *messagedata = (void*)message_getdata(ctx.message.obj); @@ -160,7 +166,7 @@ fail_target_busy: sysret = _syscall_handle_switch(&ctx); remap_return: - message_remap(ctx.message.obj, pagedir, message_vptr); + message_map(ctx.message.obj, pagedir, message_vptr); release_return: lockstack_popall(&ctx.lockstack); diff --git a/sys/syscall_objdir.c b/sys/syscall_objdir.c index 9243af1..199cbab 100644 --- a/sys/syscall_objdir.c +++ b/sys/syscall_objdir.c @@ -2,6 +2,7 @@ #include "proc/process.h" #include "jove.h" #include "lib/printf.h" +#include "sys/objdir.h" #include "syscall.h" int @@ -16,7 +17,7 @@ s_syscall_objdir_objtype( uint16_t local_idx = *((uint16_t*)payload_data); - if(local_idx > JOVE_OBJDIR_ENTRIES) { + if(local_idx > OBJDIR_ENTRIES) { kprintf("%s: Object index is out of bounds (>= 512)\n", __func__); return EOOB; } @@ -25,6 +26,85 @@ s_syscall_objdir_objtype( return obj_peektype(local_obj); } +static int +s_syscall_objdir_swap(jove_owned_obj_t *target_obj, + lockstack_t *lockstack, + jove_owned_obj_t *rootdir, + size_t bytes_left, + void *payload_data) +{ + size_t bytes_needed = sizeof(struct syscall_objdir_swap); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload."); + + 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."); + + jove_owned_obj_t *obj_a = lockstack_push(lockstack, objdir_trygetlocal(target_obj, payload->index)); + if(obj_a == NULL) { + klogf("Getting local object %i failed : %s\n", + payload->index, errstr(errno)); + return -errno; + } + jove_perm_obj_t objdir_b = link_try_traverse_objdir(rootdir, lockstack, + payload->other_path_length - 1, payload->other_path); + if(objdir_b.obj == NULL) { + klogf("Getting object %P failed : %s\n", + payload->other_path, payload->other_path_length, errstr(errno)); + return -errno; + } + + CHECK_OBJPERM(objdir_b, SYSCALL_PERM_OBJDIR_SWAP_TGT, "Other object is missing permission"); + jove_owned_obj_t *obj_b = lockstack_push(lockstack, + objdir_trygetlocal(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_owned_obj_t *rootdir_obj, + size_t bytes_left, + void *payload_data) +{ + size_t bytes_needed = sizeof(struct syscall_objdir_link); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); + + 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"); + + jove_owned_obj_t *link_obj = lockstack_push(lockstack, objdir_trygetlocal(target_obj, payload->index)); + if(link_obj == NULL) { + klogf("Getting local object %i failed : %s\n", payload->index, errstr(errno)); + return -errno; + } + CHECK_OBJTYPE(link_obj, JOVE_OBJ_LINK, "Local object is not a link object"); + + jove_perm_obj_t dest_obj = link_try_traverse_objdir(rootdir_obj, lockstack, + payload->other_path_length, payload->other_path); + if(dest_obj.obj == NULL) { + klogf("Getting destination object %P failed : %s\n", + payload->other_path, payload->other_path_length, errstr(errno)); + return -errno; + } + + 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; + } + 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) { @@ -34,6 +114,19 @@ _syscall_handle_objdir(syscall_context_t *ctx) return s_syscall_objdir_objtype( ctx->objdir, ctx->target.obj, 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->target.obj, + &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; } diff --git a/sys/syscall_pcb.c b/sys/syscall_pcb.c index 4fe557b..3aeb22b 100644 --- a/sys/syscall_pcb.c +++ b/sys/syscall_pcb.c @@ -6,17 +6,20 @@ #include "proc/process.h" #include "proc/scheduler.h" #include "syscall.h" -#include "errno.h" int s_syscall_pcb_yield(jove_owned_obj_t *pcb_obj, size_t bytes_left, void *payload_data) { + //Validate that message is big enough for payload size_t bytes_needed = sizeof(pid_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); + //Get subject PID from payload. pid_t subject_pid = *((pid_t*)payload_data); + + //Yield to target. return scheduler_yield(subject_pid); } @@ -27,13 +30,22 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj, size_t bytes_left, void *payload_data) { + //Validate that message is big enough for payload. size_t bytes_needed = sizeof(struct syscall_pcb_send); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); - struct syscall_pcb_send *payload = payload_data; + + //Validate that message is big enough for payload object path. bytes_needed += payload->send_path_length; CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for subject path"); + //Validate that subject object path is not the root directory. + if(payload->send_path_length == 0) { + kprintf("%s: Unable to send root directory\n", __func__); + return -EBADPATH; + } + + //Validate that the subject objdir path is valid. jove_perm_obj_t subject_objdir = link_try_traverse_objdir( objdir_obj, lockstack, payload->send_path_length - 1, payload->send_path); if(errno) { @@ -41,8 +53,11 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj, payload->send_path, payload->send_path_length, errstr(errno)); return -errno; } + + //Validate that the currently running PCB has mutate permissions for this objdir. CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send"); + //Validate that the subject exists in the subject objdir. jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj, payload->send_path[payload->send_path_length-1]); if(subject == 0) { @@ -51,6 +66,7 @@ s_syscall_pcb_send(jove_owned_obj_t *pcb_obj, return -errno; } + //Send subject to target. return pcb_send(obj_deref(pcb_obj), payload->send_target, subject, payload->send_timeout); } @@ -61,13 +77,16 @@ s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj, size_t bytes_left, void *payload_data) { + //Validate that the message is big enough for the payload. size_t bytes_needed = sizeof(struct syscall_pcb_recv); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); - struct syscall_pcb_recv *payload = payload_data; + + //Validate that the message is big enough for the payload object. bytes_needed += payload->recv_path_length * sizeof(objpath_part_t); CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for destination path"); + //Validate that the destination object exists. jove_perm_obj_t destination = link_try_traverse_objdir( objdir_obj, lockstack, payload->recv_path_length, payload->recv_path); if(errno) { @@ -75,12 +94,147 @@ s_syscall_pcb_recv(jove_owned_obj_t *pcb_obj, payload->recv_path, payload->recv_path_length, errstr(errno)); return -errno; } + + //Validate that the destination path is JOVE_OBJ_NONE and that the object has recieve permissions. + CHECK_OBJTYPE(destination.obj, JOVE_OBJ_NONE, "Destination object is occupied"); CHECK_OBJPERM(destination, SYSCALL_PERM_PCB_RECV_DST, "Destination object does not permit recv."); + //Recieve from some PID into destination. return pcb_recv(obj_deref(pcb_obj), payload->recv_target, destination.obj, payload->recv_timeout); } int +s_syscall_pcb_swap(jove_owned_obj_t *pcb_obj, + lockstack_t *lockstack, + jove_owned_obj_t *objdir_obj, + size_t bytes_left, + void *payload_data) +{ + //Validate that the message is big enough for payload. + size_t bytes_needed = sizeof(struct syscall_pcb_recv); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); + struct syscall_pcb_swap *payload = payload_data; + + //Validate that the message is big enough for the subject path. + bytes_needed += payload->swap_path_length * sizeof(objpath_part_t); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for swap path"); + + //Validate that the subject is not the rootdir. + if(payload->swap_path_length == 0) { + kprintf("%s: Unable to swap the root directory\n", __func__); + return -EBADPATH; + } + + //Validate that the subject objdir exists. + jove_perm_obj_t subject_objdir = link_try_traverse_objdir( + objdir_obj, lockstack, payload->swap_path_length - 1, payload->swap_path); + if(errno) { + klogf("Unable to get subject %P objdir : %s\n", + payload->swap_path, payload->swap_path_length, errstr(errno)); + return -errno; + } + //Validate that the subject objdir has send permissions. + CHECK_OBJPERM(subject_objdir, SYSCALL_PERM_PCB_SEND_OBJDIR, "Subject objdir does not permit send"); + + //Validate that the subject object exists. + jove_owned_obj_t *subject = objdir_trygetlocal(subject_objdir.obj, + payload->swap_path[payload->swap_path_length-1]); + if(subject == 0) { + klogf("Unable to get subject %P object : %s\n", + payload->swap_path, payload->swap_path_length, errstr(errno)); + return -errno; + } + + //Validate that the target PCB exists. + if(pcb_frompid(payload->swap_target) == 0) { + klogf("Swap PCB target %i does not exist\n", payload->swap_target); + return -EBADPROC; + } + + //Validate that the message was sent before timeout. + int send_result = pcb_send( + obj_deref(pcb_obj), payload->swap_target, subject, payload->send_timeout); + if(send_result < 0) { + klogf("Send to %i failed with code %s\n", payload->swap_target, errstr(-send_result)); + return send_result; + } + + //Validate that a message was recieved before timeout. + int recv_result = pcb_recv( + obj_deref(pcb_obj), payload->swap_target, subject, payload->recv_timeout); + return recv_result; +} + +int +s_syscall_pcb_stack(jove_owned_obj_t *pcb_obj, + lockstack_t *lockstack, + jove_owned_obj_t *rootdir, + size_t bytes_left, + void *payload_data) +{ + //Verify the message is big enough for the payload struct. + size_t bytes_needed = sizeof(struct syscall_pcb_stack); + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for payload"); + + //Verify the message is big enough for the untyped object path. + struct syscall_pcb_stack *payload = payload_data; + bytes_needed += sizeof(objpath_part_t) * payload->stack_path_length; + CHECK_TOOSMALL(bytes_needed, bytes_left, "Message too small for untyped path"); + + jove_perm_obj_t untyped = link_try_traverse_objdir(rootdir, lockstack, + payload->stack_path_length, payload->stack_path); + //Verify the untyped object exists. + if(untyped.obj == NULL) { + klogf("Unable to get untyped %P : %s\n", + payload->stack_path, payload->stack_path_length, errstr(errno)); + return -errno; + } + + //Verify the correct type and permissions. + CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Subject untyped is not an untyped."); + CHECK_OBJPERM(untyped, SYSCALL_PERM_PCB_STACK_OBJ, "Untyped is missing permissions"); + + jove_untyped_t *untyped_data = obj_deref(untyped.obj); + if((uintptr_t)untyped_data & 0xFFF) { + klogf("Untyped object %P is not aligned to page boundary.\n", + payload->stack_path, payload->stack_path_length); + return -EALIGN; + } + if(untyped_data->limit != 0x1000) { + klogf("Untyped object %P is not page sized.\n", + payload->stack_path, payload->stack_path_length); + return -EBADSIZE; + } + + //Set the stack. Error if bad type or stack already exists. + pcb_t *pcb = obj_deref(pcb_obj); + switch(payload->type) { + case PCB_STACK_SYSTEM: + if(pcb_get_syscall_stack(pcb) != 0) { + klogf("PCB %p Already has a system stack!\n", pcb); + return -EFULL; + } + pcb_set_syscall_stack(pcb, obj_getvalue(untyped.obj)); + break; + case PCB_STACK_INTERRUPT: + if(pcb_get_interrupt_stack(pcb) != 0) { + klogf("PCB %p Already has a interrupt stack!\n", pcb); + return -EFULL; + } + pcb_set_interrupt_stack(pcb, obj_getvalue(untyped.obj)); + break; + default: + klogf("Unknown stack type %i\n", payload->type); + return -EBADARG; + } + + //Destroy untyped object. + obj_settype(untyped.obj, JOVE_OBJ_NONE); + obj_setvalue(untyped.obj, 0); + return 0; +} + +int _syscall_handle_pcb(syscall_context_t *ctx) { switch(ctx->header->callid) { @@ -101,6 +255,18 @@ _syscall_handle_pcb(syscall_context_t *ctx) ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); return -EPERM; + case SYSCALL_PCB_SWAP: + if(ctx->target.permissions & SYSCALL_PERM_PCB_SWAP) + return s_syscall_pcb_swap( + ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); + return -EPERM; + + case SYSCALL_PCB_STACK: + if(ctx->target.permissions & SYSCALL_PERM_PCB_STACK) + return s_syscall_pcb_stack( + ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->bytes_left, ctx->payload); + return -EPERM; + default: return -EBADCALL; } diff --git a/sys/syscall_untyped.c b/sys/syscall_untyped.c index c4378ea..c64dea1 100644 --- a/sys/syscall_untyped.c +++ b/sys/syscall_untyped.c @@ -5,6 +5,7 @@ #include "jove.h" #include "lib/printf.h" #include "proc/process.h" +#include "sys/message.h" #include "sys/objdir.h" #include "syscall.h" @@ -148,6 +149,10 @@ int _syscall_handle_untyped(syscall_context_t *ctx) return s_syscall_untyped_retype_pcb( ctx->target.obj, &ctx->lockstack, ctx->objdir, ctx->header); return -EPERM; + case SYSCALL_UNTYPED_RETYPE_MESSAGE: + if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_RETYPE) + return message_new(ctx->target.obj); + return -EPERM; default: return -EBADCALL; |
