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
|
#include "api/error.h"
#include "boot/initrd.h"
#include "lib/printf.h"
#include "sys/message.h"
#include "sys/syscall.h"
#include "lib/string.h"
int
s_syscall_initrd_file_name(
jove_owned_obj_t *initrd_file,
jove_owned_obj_t *message)
{
const char *filename = initrd_file_name(initrd_file);
size_t filename_len = strlen(filename);
size_t bytes_left = message_len(message);
size_t bytes_needed = filename_len + sizeof(struct syscall_initrd_file_name_ret);
CHECK_TOOSMALL(bytes_needed, bytes_left, "Message is too small for file name.");
struct syscall_initrd_file_name_ret *payload = message_data(message);
payload->len = filename_len;
memcpy(payload->c_str, filename, filename_len);
return 0;
}
int
s_syscall_initrd_file_size(jove_owned_obj_t *initrd_file)
{
return initrd_file_size(initrd_file);
}
int
s_syscall_initrd_file_read(
jove_owned_obj_t *initrd_file,
jove_owned_obj_t *message,
size_t bytes_left,
void *payload_data)
{
//Ensure that the message payload could hold the required read payload.
size_t bytes_needed = sizeof(struct syscall_initrd_file_read);
CHECK_TOOSMALL(bytes_needed, bytes_left,
"Message is too small to hold read payload.");
struct syscall_initrd_file_read *payload = payload_data;
bytes_needed = payload->read_size;
bytes_left = message_len(message);
//Ensure that the message is big enough to hold the read file data.
CHECK_TOOSMALL(bytes_needed, bytes_left,
"Message is too small to hold read bytes.");
size_t file_size = initrd_file_size(initrd_file);
char *file_data = initrd_file_data(initrd_file);
//Ensure that the start index is within the file.
if(payload->start_index >= file_size) {
klogf("Start index exceeds file length! (%i > %i)\n",
payload->start_index, file_size);
return -EOOB;
}
//Ensure that the read bounds is within the file.
if(payload->start_index + payload->read_size > file_size) {
klogf("Read bounds exceed file length! (%i+%i > %i)\n",
payload->start_index, payload->read_size, file_size);
return -ETOOBIG;
}
void *read_data = message_data(message);
memcpy(read_data, file_data + payload->start_index, payload->read_size);
return 0;
}
int
_syscall_handle_initrd_file(syscall_context_t *ctx)
{
switch(ctx->header->callid) {
case SYSCALL_INITRD_FILE_NAME:
if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_NAME)
return s_syscall_initrd_file_name(
ctx->target.obj, ctx->message.obj);
return -EPERM;
case SYSCALL_INITRD_FILE_SIZE:
if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_SIZE)
return s_syscall_initrd_file_size(ctx->target.obj);
return -EPERM;
case SYSCALL_INITRD_FILE_READ:
if(ctx->target.permissions & SYSCALL_PERM_INITRD_FILE_READ)
return s_syscall_initrd_file_read(
ctx->target.obj, ctx->message.obj, ctx->bytes_left, ctx->payload);
return -EPERM;
default:
return -EBADCALL;
}
}
|