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
|
#include "arch/x86_64/hal/obj.h"
#include "hal/memory.h"
#include "jove.h"
#include "lib/printf.h"
#include "syscall.h"
static int
s_syscall_untyped_split(
lockstack_t *lockstack,
jove_owned_obj_t *objdir,
jove_owned_obj_t *target_obj,
size_t payload_bytes,
void *payload_data)
{
int bytes_needed = sizeof(struct syscall_untyped_split);
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for payload!");
struct syscall_untyped_split *payload = payload_data;
bytes_needed += payload->dest_pathlen * 2;
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for destination path!");
jove_perm_obj_t dest = link_try_traverse_objdir(
objdir, lockstack, payload->dest_pathlen, payload->dest_path);
if(errno) {
klogf("Unable to get destination object %P: %s\n",
payload->dest_path, payload->dest_pathlen, errstr(errno));
return errno;
}
CHECK_OBJTYPE(dest.obj, JOVE_OBJ_NONE, "Destination path is occupied!");
if(payload->bytes < JOVE_UNTYPED_MINSIZE) {
klogf("Destination untyped would be too small. (%X < %X)\n",
payload->bytes, JOVE_UNTYPED_MINSIZE);
return -ETOOBIG;
}
return untyped_split(target_obj, dest.obj, payload->bytes);
}
static int
s_syscall_untyped_merge(
lockstack_t *lockstack,
jove_owned_obj_t *objdir,
jove_owned_obj_t *target_obj,
size_t payload_bytes,
void *payload_data)
{
int bytes_needed = sizeof(struct syscall_generic_objpath);
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for payload!");
struct syscall_generic_objpath *payload = payload_data;
bytes_needed += payload->pathlen * 2;
CHECK_TOOSMALL(bytes_needed, payload_bytes, "Message is too small for second path!");
jove_perm_obj_t untyped = link_try_traverse_objdir(
objdir, lockstack, payload->pathlen, payload->path);
if(errno) {
klogf("Unable to retrieve untyped object %P : %s\n",
payload->path, payload->pathlen, errstr(errno));
return errno;
}
CHECK_OBJTYPE(untyped.obj, JOVE_OBJ_UNTYPED, "Second object is not an untyped!");
CHECK_OBJPERM(untyped, SYSCALL_PERM_UNTYPED_MERGE, "Second untyped does not have permission to merge!");
int sysret = untyped_merge(target_obj, untyped.obj);
if(obj_gettype(untyped.obj) == JOVE_OBJ_UNTYPED) {
//Untyped merged into second object. We need to switch objects.
obj_settype(target_obj, JOVE_OBJ_UNTYPED);
obj_setvalue(target_obj, obj_getvalue(untyped.obj));
obj_settype(untyped.obj, JOVE_OBJ_NONE);
}
return sysret;
}
int _syscall_handle_untyped(syscall_context_t *ctx)
{
switch(ctx->header->callid) {
case SYSCALL_UNTYPED_ADDRESS:
if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_ADDRESS)
return untyped_address(ctx->target.obj);
return -EPERM;
case SYSCALL_UNTYPED_SIZE:
if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SIZE)
return untyped_size(ctx->target.obj);
return -EPERM;
case SYSCALL_UNTYPED_SPLIT:
if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_SPLIT)
return s_syscall_untyped_split(
&ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload);
return -EPERM;
case SYSCALL_UNTYPED_MERGE:
if(ctx->target.permissions & SYSCALL_PERM_UNTYPED_MERGE)
return s_syscall_untyped_merge(
&ctx->lockstack, ctx->objdir, ctx->target.obj, ctx->bytes_left, ctx->payload);
return -EPERM;
default:
return -EBADCALL;
}
return 0;
}
|