forked from keystone-enclave/keystone-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
edge_call.c
127 lines (105 loc) · 3.59 KB
/
edge_call.c
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
//******************************************************************************
// Copyright (c) 2018, The Regents of the University of California (Regents).
// All Rights Reserved. See LICENSE for license details.
//------------------------------------------------------------------------------
#include <edge_call.h>
#include "string.h"
#include <sys/epoll.h>
#include <sys/socket.h>
uintptr_t _shared_start;
size_t _shared_len;
void
edge_call_init_internals(uintptr_t buffer_start, size_t buffer_len) {
_shared_start = buffer_start;
_shared_len = buffer_len;
}
int
edge_call_get_ptr_from_offset(
edge_data_offset offset, size_t data_len, uintptr_t* ptr) {
// TODO double check these checks
/* Validate that _shared_start+offset is sane */
if (offset > UINTPTR_MAX - _shared_start || offset > _shared_len) {
return -1;
}
/* Validate that _shared_start+offset+data_len in range */
if (data_len > UINTPTR_MAX - (_shared_start + offset) ||
data_len > _shared_len - offset) {
return -1;
}
/* ptr looks valid, create it */
*ptr = _shared_start + offset;
return 0;
}
int
edge_call_check_ptr_valid(uintptr_t ptr, size_t data_len) {
// TODO double check these checks
/* Validate that ptr starts in range */
if (ptr > _shared_start + _shared_len || ptr < _shared_start) {
return 1;
}
if (data_len > UINTPTR_MAX - ptr) {
return 2;
}
/* Validate that the end is in range */
if (ptr + data_len > _shared_start + _shared_len) {
return 3;
}
return 0;
}
int
edge_call_get_offset_from_ptr(
uintptr_t ptr, size_t data_len, edge_data_offset* offset) {
int valid = edge_call_check_ptr_valid(ptr, data_len);
if (valid != 0) return valid;
/* ptr looks valid, create it */
*offset = ptr - _shared_start;
return 0;
}
int
edge_call_args_ptr(struct edge_call* edge_call, uintptr_t* ptr, size_t* size) {
*size = edge_call->call_arg_size;
return edge_call_get_ptr_from_offset(edge_call->call_arg_offset, *size, ptr);
}
int
edge_call_ret_ptr(struct edge_call* edge_call, uintptr_t* ptr, size_t* size) {
*size = edge_call->return_data.call_ret_size;
return edge_call_get_ptr_from_offset(
edge_call->return_data.call_ret_offset, *size, ptr);
}
int
edge_call_setup_call(struct edge_call* edge_call, void* ptr, size_t size) {
edge_call->call_arg_size = size;
return edge_call_get_offset_from_ptr(
(uintptr_t)ptr, size, &edge_call->call_arg_offset);
}
int
edge_call_setup_ret(struct edge_call* edge_call, void* ptr, size_t size) {
edge_call->return_data.call_ret_size = size;
return edge_call_get_offset_from_ptr(
(uintptr_t)ptr, size, &edge_call->return_data.call_ret_offset);
}
/* This is only usable for the host */
int
edge_call_setup_wrapped_ret(
struct edge_call* edge_call, void* ptr, size_t size) {
struct edge_data data_wrapper;
data_wrapper.size = size;
edge_call_get_offset_from_ptr(
_shared_start + sizeof(struct edge_call) + sizeof(struct edge_data),
sizeof(struct edge_data), &data_wrapper.offset);
memcpy(
(void*)(_shared_start + sizeof(struct edge_call) + sizeof(struct edge_data)),
ptr, size);
memcpy(
(void*)(_shared_start + sizeof(struct edge_call)), &data_wrapper,
sizeof(struct edge_data));
edge_call->return_data.call_ret_size = sizeof(struct edge_data);
return edge_call_get_offset_from_ptr(
_shared_start + sizeof(struct edge_call), sizeof(struct edge_data),
&edge_call->return_data.call_ret_offset);
}
/* This is temporary until we have a better way to handle multiple things */
uintptr_t
edge_call_data_ptr() {
return _shared_start + sizeof(struct edge_call);
}