summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-10-13 22:31:43 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-10-13 22:31:43 -0400
commit548506392b789f58b1556a6ffca917441e1d89fd (patch)
tree58e4b747446ea64e7951e523353f58510b3a8b2f /sys
parentc5e3bb7917689bc9ed54fee23a143144fade802d (diff)
downloadjove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.gz
jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.tar.bz2
jove-kernel-548506392b789f58b1556a6ffca917441e1d89fd.zip
ipc functions. work on process spawning
Diffstat (limited to 'sys')
-rw-r--r--sys/link.c58
-rw-r--r--sys/link.h24
-rw-r--r--sys/message.c96
-rw-r--r--sys/message.h13
-rw-r--r--sys/objdir.c13
-rw-r--r--sys/syscall.c8
-rw-r--r--sys/syscall_objdir.c95
-rw-r--r--sys/syscall_pcb.c172
-rw-r--r--sys/syscall_untyped.c5
9 files changed, 377 insertions, 107 deletions
diff --git a/sys/link.c b/sys/link.c
index 04a15cf..cda10c6 100644
--- a/sys/link.c
+++ b/sys/link.c
@@ -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;
-}
diff --git a/sys/link.h b/sys/link.h
index d4bc8d8..5659101 100644
--- a/sys/link.h
+++ b/sys/link.h
@@ -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;