diff options
| author | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-13 22:31:43 -0400 |
|---|---|---|
| committer | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-13 22:31:43 -0400 |
| commit | 548506392b789f58b1556a6ffca917441e1d89fd (patch) | |
| tree | 58e4b747446ea64e7951e523353f58510b3a8b2f /sys/syscall_pcb.c | |
| parent | c5e3bb7917689bc9ed54fee23a143144fade802d (diff) | |
| download | jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.gz jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.bz2 jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.zip | |
ipc functions. work on process spawning
Diffstat (limited to 'sys/syscall_pcb.c')
| -rw-r--r-- | sys/syscall_pcb.c | 172 |
1 files changed, 169 insertions, 3 deletions
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; } |
