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

Contents of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 343 - (show annotations) (download) (as text)
Thu Jul 13 16:17:56 2006 UTC (8 years, 4 months ago) by azarah
File MIME type: text/x-csrc
File size: 10194 byte(s)
Punt vim indentation line.

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20