/[path-sandbox]/trunk/src/sandbox.c
Gentoo

Contents of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 401 - (show annotations) (download) (as text)
Mon Nov 10 22:17:21 2008 UTC (5 years, 8 months ago) by vapier
File MIME type: text/x-csrc
File size: 9144 byte(s)
convert to stdbool
1 /*
2 * sandbox.c
3 *
4 * Main sandbox related functions.
5 *
6 * Copyright 1999-2008 Gentoo Foundation
7 * Licensed under the GPL-2
8 *
9 * Some parts might have Copyright:
10 *
11 * Copyright (C) 2002 Brad House <brad@mainstreetsoftworks.com>
12 */
13
14 #include "headers.h"
15 #include "sbutil.h"
16 #include "sandbox.h"
17
18 static int print_debug = 0;
19
20 volatile static int stop_called = 0;
21 volatile static pid_t child_pid = 0;
22
23 static char log_domain[] = "sandbox";
24 static const char sandbox_banner[] = "============================= Gentoo path sandbox ==============================";
25
26 int setup_sandbox(struct sandbox_info_t *sandbox_info, bool interactive)
27 {
28 if (NULL != getenv(ENV_PORTAGE_TMPDIR)) {
29 /* Portage handle setting SANDBOX_WRITE itself. */
30 sandbox_info->work_dir[0] = '\0';
31 } else {
32 if (NULL == getcwd(sandbox_info->work_dir, SB_PATH_MAX)) {
33 perror("sandbox: Failed to get current directory");
34 return -1;
35 }
36 if (interactive)
37 setenv(ENV_SANDBOX_WORKDIR, sandbox_info->work_dir, 1);
38 }
39
40 /* Do not resolve symlinks, etc .. libsandbox will handle that. */
41 if (!rc_is_dir(VAR_TMPDIR, true)) {
42 perror("sandbox: Failed to get var_tmp_dir");
43 return -1;
44 }
45 snprintf(sandbox_info->var_tmp_dir, SB_PATH_MAX, "%s", VAR_TMPDIR);
46
47 if (-1 == get_tmp_dir(sandbox_info->tmp_dir)) {
48 perror("sandbox: Failed to get tmp_dir");
49 return -1;
50 }
51 setenv(ENV_TMPDIR, sandbox_info->tmp_dir, 1);
52
53 sandbox_info->home_dir = getenv("HOME");
54 if (!sandbox_info->home_dir) {
55 sandbox_info->home_dir = sandbox_info->tmp_dir;
56 setenv("HOME", sandbox_info->home_dir, 1);
57 }
58
59 /* Generate sandbox lib path */
60 get_sandbox_lib(sandbox_info->sandbox_lib);
61
62 /* Generate sandbox bashrc path */
63 get_sandbox_rc(sandbox_info->sandbox_rc);
64
65 /* Generate sandbox log full path */
66 get_sandbox_log(sandbox_info->sandbox_log);
67 if (rc_file_exists(sandbox_info->sandbox_log)) {
68 if (-1 == unlink(sandbox_info->sandbox_log)) {
69 perror("sandbox: Could not unlink old log file");
70 return -1;
71 }
72 }
73
74 /* Generate sandbox debug log full path */
75 get_sandbox_debug_log(sandbox_info->sandbox_debug_log);
76 if (rc_file_exists(sandbox_info->sandbox_debug_log)) {
77 if (-1 == unlink(sandbox_info->sandbox_debug_log)) {
78 perror("sandbox: Could not unlink old debug log file");
79 return -1;
80 }
81 }
82
83 return 0;
84 }
85
86 int print_sandbox_log(char *sandbox_log)
87 {
88 int sandbox_log_file = -1;
89 char *beep_count_env = NULL;
90 int i, color, beep_count = 0;
91 off_t len = 0;
92 char *buffer = NULL;
93
94 if (!rc_is_file(sandbox_log, false)) {
95 perror("sandbox: Log file is not a regular file");
96 return 0;
97 }
98
99 len = rc_get_size(sandbox_log, true);
100 if (0 == len)
101 return 0;
102
103 sandbox_log_file = sb_open(sandbox_log, O_RDONLY, 0);
104 if (-1 == sandbox_log_file) {
105 perror("sandbox: Could not open Log file");
106 return 0;
107 }
108
109 buffer = xmalloc((len + 1) * sizeof(char));
110 if (NULL == buffer) {
111 perror("sandbox: Could not allocate buffer for Log file");
112 return 0;
113 }
114 memset(buffer, 0, len + 1);
115 if (-1 == sb_read(sandbox_log_file, buffer, len)) {
116 perror("sandbox: Could read Log file");
117 return 0;
118 }
119 sb_close(sandbox_log_file);
120
121 color = ((is_env_on(ENV_NOCOLOR)) ? 0 : 1);
122
123 SB_EERROR(color,
124 "--------------------------- ACCESS VIOLATION SUMMARY ---------------------------",
125 "\n");
126 SB_EERROR(color, "LOG FILE = \"%s\"", "\n\n", sandbox_log);
127 fprintf(stderr, "%s", buffer);
128 free(buffer);
129 SB_EERROR(color,
130 "--------------------------------------------------------------------------------",
131 "\n");
132
133 beep_count_env = getenv(ENV_SANDBOX_BEEP);
134 if (beep_count_env)
135 beep_count = atoi(beep_count_env);
136 else
137 beep_count = DEFAULT_BEEP_COUNT;
138
139 for (i = 0; i < beep_count; i++) {
140 fputc('\a', stderr);
141 if (i < beep_count - 1)
142 sleep(1);
143 }
144
145 return 1;
146 }
147
148 void stop(int signum)
149 {
150 if (0 == stop_called) {
151 stop_called = 1;
152 printf("sandbox: Caught signal %d in pid %d\n",
153 signum, getpid());
154 } else {
155 fprintf(stderr,
156 "sandbox: Signal already caught and busy still cleaning up!\n");
157 }
158 }
159
160 void usr1_handler(int signum, siginfo_t *siginfo, void *ucontext)
161 {
162 if (0 == stop_called) {
163 stop_called = 1;
164 printf("sandbox: Caught signal %d in pid %d\n",
165 signum, getpid());
166
167 /* FIXME: This is really bad form, as we should kill the whole process
168 * tree, but currently that is too much work and not worth the
169 * effort. Thus we only kill the calling process and our child
170 * for now.
171 */
172 if (siginfo->si_pid > 0)
173 kill(siginfo->si_pid, SIGKILL);
174 kill(child_pid, SIGKILL);
175 } else {
176 fprintf(stderr,
177 "sandbox: Signal already caught and busy still cleaning up!\n");
178 }
179 }
180
181 int spawn_shell(char *argv_bash[], char **env, int debug)
182 {
183 int status = 0;
184 int ret = 0;
185
186 child_pid = fork();
187
188 /* Child's process */
189 if (0 == child_pid) {
190 execve(argv_bash[0], argv_bash, env);
191 _exit(EXIT_FAILURE);
192 } else if (child_pid < 0) {
193 if (debug)
194 fprintf(stderr, "Process failed to spawn!\n");
195 return 0;
196 }
197
198 /* fork() creates a copy of this, so no need to use more memory than
199 * absolutely needed. */
200 str_list_free(argv_bash);
201 str_list_free(env);
202
203 ret = waitpid(child_pid, &status, 0);
204 if ((-1 == ret) || (status > 0)) {
205 if (debug)
206 fprintf(stderr, "Process returned with failed exit status!\n");
207 return 0;
208 }
209
210 return 1;
211 }
212
213 int main(int argc, char **argv)
214 {
215 struct sigaction act_new;
216
217 int success = 1;
218 int sandbox_log_presence = 0;
219
220 struct sandbox_info_t sandbox_info;
221
222 char **sandbox_environ;
223 char **argv_bash = NULL;
224
225 char *run_str = "-c";
226
227 rc_log_domain(log_domain);
228
229 /* Only print info if called with no arguments .... */
230 if (argc < 2)
231 print_debug = 1;
232
233 if (print_debug)
234 puts(sandbox_banner);
235
236 /* check if a sandbox is already running */
237 if (NULL != getenv(ENV_SANDBOX_ACTIVE)) {
238 fprintf(stderr, "Not launching a new sandbox instance\n");
239 fprintf(stderr, "Another one is already running in this process hierarchy.\n");
240 exit(EXIT_FAILURE);
241 }
242
243 /* determine the location of all the sandbox support files */
244 if (print_debug)
245 printf("Detection of the support files.\n");
246
247 if (-1 == setup_sandbox(&sandbox_info, print_debug)) {
248 fprintf(stderr, "sandbox: Failed to setup sandbox.");
249 exit(EXIT_FAILURE);
250 }
251
252 /* verify the existance of required files */
253 if (print_debug)
254 printf("Verification of the required files.\n");
255
256 if (!rc_file_exists(sandbox_info.sandbox_rc)) {
257 perror("sandbox: Could not open the sandbox rc file");
258 exit(EXIT_FAILURE);
259 }
260
261 /* set up the required environment variables */
262 if (print_debug)
263 printf("Setting up the required environment variables.\n");
264
265 /* If not in portage, cd into it work directory */
266 if ('\0' != sandbox_info.work_dir[0])
267 chdir(sandbox_info.work_dir);
268
269 /* Setup the child environment stuff.
270 * XXX: We free this in spawn_shell(). */
271 sandbox_environ = setup_environ(&sandbox_info, print_debug);
272 if (NULL == sandbox_environ)
273 goto oom_error;
274
275 /* Setup bash argv */
276 str_list_add_item_copy(argv_bash, "/bin/bash", oom_error);
277 str_list_add_item_copy(argv_bash, "-rcfile", oom_error);
278 str_list_add_item_copy(argv_bash, sandbox_info.sandbox_rc, oom_error);
279 if (argc >= 2) {
280 int i;
281
282 str_list_add_item_copy(argv_bash, run_str, oom_error);
283 str_list_add_item_copy(argv_bash, argv[1], oom_error);
284 for (i = 2; i < argc; i++) {
285 char *tmp_ptr;
286
287 tmp_ptr = xrealloc(argv_bash[4],
288 (strlen(argv_bash[4]) +
289 strlen(argv[i]) + 2) *
290 sizeof(char));
291 if (NULL == tmp_ptr)
292 goto oom_error;
293 argv_bash[4] = tmp_ptr;
294
295 snprintf(argv_bash[4] + strlen(argv_bash[4]),
296 strlen(argv[i]) + 2, " %s",
297 argv[i]);
298 }
299 }
300
301 /* set up the required signal handlers */
302 signal(SIGHUP, &stop);
303 signal(SIGINT, &stop);
304 signal(SIGQUIT, &stop);
305 signal(SIGTERM, &stop);
306 act_new.sa_sigaction = usr1_handler;
307 sigemptyset (&act_new.sa_mask);
308 act_new.sa_flags = SA_SIGINFO | SA_RESTART;
309 sigaction (SIGUSR1, &act_new, NULL);
310
311 /* STARTING PROTECTED ENVIRONMENT */
312 if (print_debug) {
313 printf("The protected environment has been started.\n");
314 printf("--------------------------------------------------------------------------------\n");
315 }
316
317 if (print_debug)
318 printf("Process being started in forked instance.\n");
319
320 /* Start Bash */
321 if (!spawn_shell(argv_bash, sandbox_environ, print_debug))
322 success = 0;
323
324 /* As spawn_shell() free both argv_bash and sandbox_environ, make sure
325 * we do not run into issues in future if we need a OOM error below
326 * this ... */
327 argv_bash = NULL;
328 sandbox_environ = NULL;
329
330 if (print_debug)
331 printf("Cleaning up sandbox process\n");
332
333 if (print_debug) {
334 puts(sandbox_banner);
335 printf("The protected environment has been shut down.\n");
336 }
337
338 if (rc_file_exists(sandbox_info.sandbox_log)) {
339 sandbox_log_presence = 1;
340 print_sandbox_log(sandbox_info.sandbox_log);
341 } else if (print_debug) {
342 printf("--------------------------------------------------------------------------------\n");
343 }
344
345 if ((sandbox_log_presence) || (!success))
346 return 1;
347 else
348 return 0;
349
350 oom_error:
351 if (NULL != argv_bash)
352 str_list_free(argv_bash);
353
354 perror("sandbox: Out of memory (environ)");
355 exit(EXIT_FAILURE);
356 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20