1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
#include "arch/x86_64/hal/obj.h"
#include "proc/process.h"
#include "jove.h"
#include "lib/printf.h"
#include "sys/objdir.h"
#include "syscall.h"
int
s_syscall_objdir_objtype(
jove_owned_obj_t *objdir,
jove_owned_obj_t *target_dir,
size_t payload_size,
void *payload_data)
{
size_t bytes_needed = 2;
CHECK_TOOSMALL(bytes_needed, payload_size, "Message is too small for payload.");
uint16_t local_idx = *((uint16_t*)payload_data);
if(local_idx > OBJDIR_ENTRIES) {
kprintf("%s: Object index is out of bounds (>= 512)\n", __func__);
return EOOB;
}
jove_obj_t local_obj = objdir_peeklocal(target_dir, local_idx);
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)
{
switch(ctx->header->callid) {
case SYSCALL_OBJDIR_OBJTYPE:
if(ctx->target.permissions & SYSCALL_PERM_OBJDIR_OBJTYPE)
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;
}
}
|