summaryrefslogtreecommitdiffstats
path: root/sys/syscall_objdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/syscall_objdir.c')
-rw-r--r--sys/syscall_objdir.c95
1 files changed, 94 insertions, 1 deletions
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;
}