-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsandbox.c
179 lines (141 loc) · 5.27 KB
/
sandbox.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "sandbox.h"
#include "trusted_thread.h"
#include "syscall_table.h"
#include "maps.h"
#include "common.h"
#include "tls.h"
#include <dirent.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define __USE_GNU 1
#define _GNU_SOURCE 1
struct sandbox_info sandbox;
struct sigaction sa_segv_;
void segv_sig_handler(int signo, siginfo_t *context, void *unused)
asm("segv_sig_handler") INTERNAL;
void install_sandbox_configuration(){
char * ip= NULL, * port = NULL, * visibility= NULL;
memset(&sandbox, 0, sizeof(struct sandbox_info));
if ((ip=getenv(MVH_SERVER_IP)))
{ /* Set the IP of the server from the enviroment variable*/
int ip_length=strlen(ip)+1;
int len = (ip_length>= MAX_IP_LENGTH) ? MAX_IP_LENGTH : ip_length;
strncpy(sandbox.connection.ip, ip, len);
}
else
strncpy(sandbox.connection.ip, DEFAULT_IP, sizeof(DEFAULT_IP));
// get server port
if ((port=getenv(MVH_SERVER_PORT)))
sandbox.connection.port = atoi(port);
else
sandbox.connection.port = DEFAULT_PORT;
DPRINT(DEBUG_INFO, "Remote process is at IP %s:%d\n",sandbox.connection.ip,
sandbox.connection.port);
// get server visibility
if (!(visibility=getenv(MVH_PROCESS_VISIBILITY)))
die("Process visibility has not been set corectelly");
if (!strncmp(visibility, PUBLIC_STRING, sizeof(PUBLIC_STRING)))
sandbox.visibility = PUBLIC;
else if (!strncmp(visibility, PRIVATE_STRING, sizeof(PRIVATE_STRING)))
sandbox.visibility = PRIVATE;
else
die("Imposible to recognize the visibility of the process");
sandbox.process = getpid();
sandbox.status = DISABLE;
}
void setup_signal_handlers() {
// Set SIGCHLD to SIG_DFL so that waitpid() can work
struct sigaction sa;
sigset_t mask;
memset(&mask, 0x00, sizeof(mask));
memset(&sa, 0, sizeof(sa));
sigemptyset(&mask);
sigaddset(&mask, SIGSYS);
sigaddset(&mask, SIGCHLD);
sigaddset(&mask, SIGSEGV);
sa.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &sa, NULL);
// Set up SEGV handler for dealing with RDTSC instructions, system calls
// that have been rewritten to use INT0, for sigprocmask() emulation, for
// the creation of threads, and for user-provided SEGV handlers.
sa.sa_sigaction = segv_sig_handler;
sa.sa_flags = SA_SIGINFO ;
sigaction(SIGSEGV, &sa, &sa_segv_);
// Set up SYS handler for dealing with BPF trap.
sa.sa_sigaction = emulator;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSYS, &sa, NULL);
if (sigprocmask(SIG_UNBLOCK, &mask, NULL))
die("Sigprocmask");
}
void wait_for_remote_process() {
int fd = get_local_fd();
char buf[COMMAND];
int res =-1;
memset(buf, 0, COMMAND);
DPRINT(DEBUG_INFO, "Wait for the remote process, fd %d\n", fd);
INTR_RES(read(fd, buf,COMMAND), res);
if (strncmp(buf, START_COMMAND, sizeof(START_COMMAND)) || res < COMMAND)
die("Wait for the remote process");
DPRINT(DEBUG_INFO, "Process syncronised with the remote process\n");
}
void close_file_descriptors() {
// Close all file handles except for sandboxFd, cloneFd, and stdio
DIR *dir = opendir("/proc/self/fd");
if (dir == 0) {
// If we don't know the list of our open file handles, just try closing
// all valid ones0l
// _SC_OPEN_MAX contains the maximum number of file descriptors that
// this process can open
for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; )
close(fd);
} else {
// If available, if is much more efficient to just close the file
// handles that show up in /proc/self/fd/
struct dirent de, *res;
while (!readdir_r(dir, &de, &res) && res) {
if (res->d_name[0] < '0')
continue;
int fd = atoi(res->d_name);
if (fd > 2 &&
fd != dirfd(dir)) {
close(fd);
}
}
closedir(dir);
}
}
int start_sandbox() {
install_sandbox_configuration();
DPRINT(DEBUG_INFO, "Start the sandbox enviroment of the %s process\n",
sandbox.visibility==PUBLIC ? PUBLIC_STRING : PRIVATE_STRING );
setup_signal_handlers();
DPRINT(DEBUG_INFO, "Signal handler installed\n");
/* Initialize the sytem call table containing the
* handler for each function */
initialize_syscall_table();
DPRINT(DEBUG_INFO, "System call table initialized \n");
/*TODO Rewrite VSDO and vsyscall */
// close all file descriptors open so far
close_file_descriptors();
// This may be moved to another position, only the trusted
// process uses it.
/*Get the file descriptor of the mapins */
sandbox.self_maps = open("/proc/self/maps", O_RDONLY, 0);
if (sandbox.self_maps < 0)
die("Cannot access \"/proc/self/maps\"");
/* Create the trusted thread and enter seccomp mode */
if (create_trusted_thread() < 0 )
die("Create trusted thread");
sandbox.status = ENABLE;
wait_for_remote_process();
DPRINT(DEBUG_INFO, "Ends Sandbox\n");
return 0;
}