summaryrefslogtreecommitdiffstats
path: root/sys/syscall_pagedir.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-09-26 17:11:50 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-09-26 17:11:50 -0400
commit5f813d49a08cf3c3f8cf6c422cfb6587df575f62 (patch)
treebd8872ee24580614b3eb845e1de26d465b025a09 /sys/syscall_pagedir.c
parentb6765812f7da9feccc271e8e0b06f166e8054386 (diff)
downloadjove-kernel-5f813d49a08cf3c3f8cf6c422cfb6587df575f62.tar.gz
jove-kernel-5f813d49a08cf3c3f8cf6c422cfb6587df575f62.tar.bz2
jove-kernel-5f813d49a08cf3c3f8cf6c422cfb6587df575f62.zip
add docs for syscalls. make syscall code kind-of cleaner
Diffstat (limited to 'sys/syscall_pagedir.c')
-rw-r--r--sys/syscall_pagedir.c170
1 files changed, 122 insertions, 48 deletions
diff --git a/sys/syscall_pagedir.c b/sys/syscall_pagedir.c
index 33acc87..961c477 100644
--- a/sys/syscall_pagedir.c
+++ b/sys/syscall_pagedir.c
@@ -5,12 +5,13 @@
#include "syscall.h"
static int
-s_syscall_pagedir_map(
+s_get_untyped(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pml4,
size_t payload_bytes,
void *payload_data,
- jove_owned_obj_t **untyped_ret)
+ jove_perm_obj_t *untyped_ret)
{
size_t bytes_needed = sizeof(struct syscall_pagedir_map);
CHECK_TOOSMALL(bytes_needed, payload_bytes,
@@ -27,40 +28,44 @@ s_syscall_pagedir_map(
"Message too small for untyped path.");
errno = 0;
- jove_owned_obj_t *untyped_obj = objdir_trygetobj(objdir,
- payload->untyped_path, payload->untyped_pathlen);
+ jove_perm_obj_t untyped = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->untyped_path, payload->untyped_pathlen)),
+ lockstack);
if(errno) {
kprintf("%s: Untyped obj failed for the reason: %s\n", __func__, errstr(errno));
return errno;
}
- CHECK_OBJTYPE(untyped_obj, JOVE_OBJ_UNTYPED,
+ CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED,
"Untyped path does not point to an untyped object.");
- jove_untyped_t *untyped_data = obj_deref(untyped_obj);
+ CHECK_OBJPERM(untyped, JOVE_PERM_MUTATE,
+ "Untyped object does not have MUTATE permission.");
+
+ jove_untyped_t *untyped_data = obj_deref(untyped.obj);
if((uintptr_t)untyped_data & 0xFFF) {
kprintf("%s: Untyped object is not page aligned.\n", __func__);
- obj_release(untyped_obj);
return EALIGN;
}
if(untyped_data->limit != 0x1000) {
kprintf("%s: Untyped object is not page sized. (expected 0x1000 got 0x%X)\n", __func__,
untyped_data->limit);
- obj_release(untyped_obj);
return EBADSIZE;
}
- *untyped_ret = untyped_obj;
+ *untyped_ret = untyped;
return 0;
}
static int
s_syscall_pagedir_unmap(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data,
- jove_owned_obj_t **none_ret)
+ jove_perm_obj_t *none_ret)
{
size_t bytes_needed = sizeof(struct syscall_pagedir_unmap);
CHECK_TOOSMALL(bytes_needed, payload_bytes,
@@ -76,117 +81,186 @@ s_syscall_pagedir_unmap(
CHECK_TOOSMALL(bytes_needed, payload_bytes,
"Message too small for none path");
- jove_owned_obj_t *none_obj = objdir_trygetobj(objdir,
- payload->none_path, payload->none_pathlen);
+ jove_perm_obj_t none = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->none_path, payload->none_pathlen)),
+ lockstack);
if(errno) {
kprintf("%s: None obj retrieval failed for the reason: %s\n",
__func__, errstr(errno));
return errno;
}
- CHECK_OBJTYPE(none_obj, JOVE_OBJ_NONE,
+ CHECK_OBJTYPE(none.obj, JOVE_OBJ_NONE,
"None path does not point to none object.");
- *none_ret = none_obj;
+ *none_ret = none;
return 0;
}
static int
s_syscall_pagedir_map_frame(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *untyped_obj = NULL;
- int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj);
+ jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 };
+ int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped);
if(sysret != 0) {
return sysret;
}
struct syscall_pagedir_map *payload = payload_data;
- sysret = pagedir_map_untyped_frame(target_obj, untyped_obj, payload->virtual_address, payload->flags);
+ sysret = pagedir_map_untyped_frame(pagedir, &untyped, payload->virtual_address, payload->page_flags);
if(sysret == 0)
- obj_settype(untyped_obj, JOVE_OBJ_NONE);
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
- obj_release(untyped_obj);
return sysret;
}
static int
s_syscall_pagedir_map_table(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *untyped_obj = NULL;
- int sysret = s_syscall_pagedir_map(objdir, target_obj, payload_bytes, payload_data, &untyped_obj);
+ jove_perm_obj_t untyped = { .obj = NULL, .permissions = 0 };
+ int sysret = s_get_untyped(lockstack, objdir, pagedir, payload_bytes, payload_data, &untyped);
if(sysret != 0) {
return sysret;
}
struct syscall_pagedir_map *payload = payload_data;
- sysret = pagedir_map_untyped_table(target_obj, untyped_obj, payload->virtual_address);
+ sysret = pagedir_map_untyped_table(pagedir, &untyped, payload->virtual_address);
if(sysret == 0)
- obj_settype(untyped_obj, JOVE_OBJ_NONE);
+ obj_settype(untyped.obj, JOVE_OBJ_NONE);
- obj_release(untyped_obj);
return sysret;
}
static int
+s_syscall_pagedir_map_shmem(
+ lockstack_t *lockstack,
+ jove_owned_obj_t *objdir,
+ jove_owned_obj_t *pagedir,
+ size_t payload_bytes,
+ void *payload_data)
+{
+ size_t bytes_needed = sizeof(struct syscall_pagedir_map_shmem);
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for payload.");
+
+ struct syscall_pagedir_map_shmem *payload = payload_data;
+ if(payload->virtual_address > 0xFFFF800000000000ULL) {
+ kprintf("%s: Virtual address is above user limit.\n", __func__);
+ return EBADARG;
+ }
+
+ bytes_needed += payload->shmem_pathlen << 1;
+ CHECK_TOOSMALL(bytes_needed, payload_bytes,
+ "Message too small for untyped path.");
+
+ errno = 0;
+ jove_perm_obj_t shmem = link_try_traverse(
+ lockstack_push(lockstack, objdir_trygetobj(
+ objdir, payload->shmem_path, payload->shmem_pathlen)),
+ lockstack);
+ if(errno) {
+ klogf("Shared memory obj failed for the reason: %s\n", errstr(errno));
+ return errno;
+ }
+
+ CHECK_OBJTYPE(shmem.obj, JOVE_OBJ_SHMEMORY,
+ "Shared memory path does not point to a shared memory object.");
+
+ uintmax_t shmem_value = obj_getvalue(shmem.obj);
+ uint8_t shmem_pages = shmem_value & 0xFF;
+
+ if(payload->page_offset >= shmem_pages) {
+ klogf("Page offset goes beyond size of shared memory object: (%i >= %i)\n",
+ payload->page_offset, shmem_pages);
+ return -EOOB;
+ }
+
+ return pagedir_map_shmem_frame(pagedir, &shmem, payload->page_offset,
+ payload->virtual_address, payload->page_flags);
+}
+
+static int
s_syscall_pagedir_unmap_frame(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *none_obj;
- int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj);
+ jove_perm_obj_t none;
+ int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none);
if(!sysret) return sysret;
struct syscall_pagedir_unmap *payload = payload_data;
- return pagedir_unmap_untyped_frame(target_obj, none_obj, payload->virtual_address);
+ return pagedir_unmap_untyped_frame(pagedir, none.obj, payload->virtual_address);
}
static int
s_syscall_pagedir_unmap_table(
+ lockstack_t *lockstack,
jove_owned_obj_t *objdir,
- jove_owned_obj_t *target_obj,
+ jove_owned_obj_t *pagedir,
size_t payload_bytes,
void *payload_data)
{
- jove_owned_obj_t *none_obj;
- int sysret = s_syscall_pagedir_unmap(objdir, target_obj, payload_bytes, payload_data, &none_obj);
+ jove_perm_obj_t none;
+ int sysret = s_syscall_pagedir_unmap(lockstack, objdir, pagedir, payload_bytes, payload_data, &none);
if(!sysret) return sysret;
struct syscall_pagedir_unmap *payload = payload_data;
- return pagedir_unmap_untyped_table(target_obj, none_obj, payload->virtual_address);
+ return pagedir_unmap_untyped_table(pagedir, none.obj, payload->virtual_address);
}
int
-_syscall_handle_pagedir(
- jove_owned_obj_t *pcb_obj,
- jove_owned_obj_t *objdir,
- jove_owned_obj_t *message_obj,
- jove_owned_obj_t *target_obj,
- struct syscall_header *header,
- size_t bytes_left,
- void *payload)
+_syscall_handle_pagedir(syscall_context_t *ctx)
{
+ lockstack_t *lockstack = &ctx->lockstack;
+ struct syscall_header *header = ctx->header;
+ jove_owned_obj_t *objdir = ctx->objdir;
+ jove_perm_obj_t *target = &ctx->target;
+ size_t bytes_left = ctx->bytes_left;
+ void *payload = ctx->payload;
+
switch(header->callid) {
case SYSCALL_PAGEDIR_MAP_FRAME:
- return s_syscall_pagedir_map_frame(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_FRAME)
+ return s_syscall_pagedir_map_frame(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_MAP_TABLE:
- return s_syscall_pagedir_map_table(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_TABLE)
+ return s_syscall_pagedir_map_table(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
+ case SYSCALL_PAGEDIR_MAP_SHMEM:
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_MAP_SHMEM)
+ return s_syscall_pagedir_map_shmem(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_UNMAP_FRAME:
- return s_syscall_pagedir_unmap_frame(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_FRAME)
+ return s_syscall_pagedir_unmap_frame(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
case SYSCALL_PAGEDIR_UNMAP_TABLE:
- return s_syscall_pagedir_unmap_table(objdir, target_obj, bytes_left, payload);
+ if(target->permissions & SYSCALL_PERM_PAGEDIR_UNMAP_TABLE)
+ return s_syscall_pagedir_unmap_table(lockstack, objdir, target->obj, bytes_left, payload);
+ return -EPERM;
+
default:
kprintf("syscall_handle_pagedir: Pagedir does not support syscall %i\n", header->callid);
return EBADARG;