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

Contents of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 152 - (hide annotations) (download) (as text)
Wed Jul 27 18:04:35 2005 UTC (9 years, 1 month ago) by azarah
Original Path: trunk/sandbox.c
File MIME type: text/x-csrc
File size: 15285 byte(s)
Do not resolve symlinks in PORTAGE_TMPDIR in sandbox .. we will handle that
in libsandbox .. bug #100309.

1 ferringb 2 /*
2     ** Path sandbox for the gentoo linux portage package system, initially
3     ** based on the ROCK Linux Wrapper for getting a list of created files
4     **
5     ** to integrate with bash, bash should have been built like this
6     **
7     ** ./configure --prefix=<prefix> --host=<host> --without-gnu-malloc
8     **
9     ** it's very important that the --enable-static-link option is NOT specified
10     **
11     ** Copyright (C) 2001 Geert Bevin, Uwyn, http://www.uwyn.com
12     ** Distributed under the terms of the GNU General Public License, v2 or later
13     ** Author : Geert Bevin <gbevin@uwyn.com>
14     ** $Header$
15     */
16    
17     /* #define _GNU_SOURCE */
18    
19     #include <errno.h>
20     #include <signal.h>
21     #include <stdio.h>
22     #include <stdlib.h>
23     #include <limits.h>
24     #include <string.h>
25     #include <sys/wait.h>
26     #include <unistd.h>
27     #include <fcntl.h>
28 azarah 142
29 ferringb 2 #include "sandbox.h"
30    
31 azarah 101 struct sandbox_info_t {
32     char sandbox_log[SB_PATH_MAX];
33     char sandbox_debug_log[SB_PATH_MAX];
34     char sandbox_lib[SB_PATH_MAX];
35     char sandbox_rc[SB_PATH_MAX];
36     char portage_tmp_dir[SB_PATH_MAX];
37     char var_tmp_dir[SB_PATH_MAX];
38     char tmp_dir[SB_PATH_MAX];
39     char *home_dir;
40     } sandbox_info_t;
41 ferringb 2
42 azarah 101 static char *tmp_dir;
43    
44 azarah 99 static int print_debug = 0;
45     static int stop_called = 0;
46    
47 azarah 141 int sandbox_setup(struct sandbox_info_t *sandbox_info)
48 azarah 101 {
49 azarah 152 /* Do not resolve symlinks, etc .. libsandbox will handle that. */
50     if (1 != is_dir(getenv(ENV_PORTAGE_TMPDIR) ? getenv(ENV_PORTAGE_TMPDIR)
51     : PORTAGE_TMPDIR, 1)) {
52 azarah 145 perror("sandbox: Failed to get portage_tmp_dir");
53 azarah 101 return -1;
54     }
55 azarah 152 snprintf(sandbox_info->portage_tmp_dir, SB_PATH_MAX, "%s",
56     getenv(ENV_PORTAGE_TMPDIR) ? getenv(ENV_PORTAGE_TMPDIR)
57     : PORTAGE_TMPDIR);
58 azarah 108 setenv(ENV_PORTAGE_TMPDIR, sandbox_info->portage_tmp_dir, 1);
59 azarah 101
60 azarah 152 /* Do not resolve symlinks, etc .. libsandbox will handle that. */
61     if (1 != is_dir(VAR_TMPDIR, 1)) {
62 azarah 145 perror("sandbox: Failed to get var_tmp_dir");
63 azarah 101 return -1;
64     }
65 azarah 152 snprintf(sandbox_info->var_tmp_dir, SB_PATH_MAX, "%s", VAR_TMPDIR);
66 azarah 139
67 azarah 101 if (-1 == get_tmp_dir(sandbox_info->tmp_dir)) {
68 azarah 145 perror("sandbox: Failed to get tmp_dir");
69 azarah 101 return -1;
70     }
71     tmp_dir = sandbox_info->tmp_dir;
72 azarah 108 setenv(ENV_TMPDIR, tmp_dir, 1);
73 azarah 101
74     sandbox_info->home_dir = getenv("HOME");
75     if (!sandbox_info->home_dir) {
76     sandbox_info->home_dir = tmp_dir;
77     setenv("HOME", sandbox_info->home_dir, 1);
78     }
79    
80     /* Generate sandbox lib path */
81 azarah 140 get_sandbox_lib(sandbox_info->sandbox_lib);
82 azarah 101
83     /* Generate sandbox bashrc path */
84 azarah 140 get_sandbox_rc(sandbox_info->sandbox_rc);
85 azarah 101
86     /* Generate sandbox log full path */
87 azarah 140 get_sandbox_log(sandbox_info->sandbox_log);
88 azarah 146 if (1 == exists(sandbox_info->sandbox_log)) {
89     if (-1 == unlink(sandbox_info->sandbox_log)) {
90     perror("sandbox: Could not unlink old log file");
91 azarah 147 return -1;
92 azarah 146 }
93     }
94 azarah 101
95     /* Generate sandbox debug log full path */
96 azarah 140 get_sandbox_debug_log(sandbox_info->sandbox_debug_log);
97 azarah 147 if (1 == exists(sandbox_info->sandbox_debug_log)) {
98 azarah 146 if (-1 == unlink(sandbox_info->sandbox_debug_log)) {
99     perror("sandbox: Could not unlink old debug log file");
100 azarah 147 return -1;
101 azarah 146 }
102     }
103 azarah 101
104     return 0;
105     }
106    
107 azarah 88 int print_sandbox_log(char *sandbox_log)
108     {
109     int sandbox_log_file = -1;
110     char *beep_count_env = NULL;
111     int i, color, beep_count = 0;
112     long len = 0;
113     char *buffer = NULL;
114    
115 azarah 139 if (1 != is_file(sandbox_log)) {
116 azarah 145 perror("sandbox: Log file is not a regular file");
117 azarah 88 return 0;
118 azarah 139 }
119    
120     sandbox_log_file = open(sandbox_log, O_RDONLY);
121     if (-1 == sandbox_log_file) {
122 azarah 145 perror("sandbox: Could not open Log file");
123 azarah 139 return 0;
124     }
125 azarah 88
126     len = file_length(sandbox_log_file);
127     buffer = (char *)malloc((len + 1) * sizeof(char));
128     memset(buffer, 0, len + 1);
129     read(sandbox_log_file, buffer, len);
130 azarah 139 close(sandbox_log_file);
131 azarah 88
132     color = ((getenv("NOCOLOR") != NULL) ? 0 : 1);
133    
134 azarah 144 EERROR(color,
135     "--------------------------- ACCESS VIOLATION SUMMARY ---------------------------",
136     "\n");
137     EERROR(color, "LOG FILE = \"%s\"", "\n\n", sandbox_log);
138     fprintf(stderr, "%s", buffer);
139     if (NULL != buffer)
140 azarah 88 free(buffer);
141 azarah 144 EERROR(color,
142     "--------------------------------------------------------------------------------",
143     "\n");
144 azarah 88
145     beep_count_env = getenv(ENV_SANDBOX_BEEP);
146     if (beep_count_env)
147     beep_count = atoi(beep_count_env);
148     else
149     beep_count = DEFAULT_BEEP_COUNT;
150    
151     for (i = 0; i < beep_count; i++) {
152     fputc('\a', stderr);
153     if (i < beep_count - 1)
154     sleep(1);
155     }
156 azarah 139
157 azarah 88 return 1;
158     }
159    
160 azarah 30 void stop(int signum)
161 ferringb 2 {
162     if (stop_called == 0) {
163     stop_called = 1;
164 azarah 145 printf("sandbox: Caught signal %d in pid %d\n",
165     signum, getpid());
166 ferringb 2 } else {
167 azarah 145 fprintf(stderr,
168     "sandbox: Signal already caught and busy still cleaning up!\n");
169 ferringb 2 }
170     }
171    
172 azarah 101 void get_sandbox_write_envvar(char *buf, struct sandbox_info_t *sandbox_info)
173 ferringb 2 {
174 azarah 89 /* bzero out entire buffer then append trailing 0 */
175 azarah 93 memset(buf, 0, SB_BUF_LEN);
176 azarah 30
177 azarah 89 /* these could go into make.globals later on */
178     snprintf(buf, SB_BUF_LEN,
179     "%s:%s/.gconfd/lock:%s/.bash_history:%s:%s:%s:%s",
180 azarah 113 "/dev/zero:/dev/null:/dev/fd:/proc/self/fd:/dev/pts/:"
181 azarah 105 "/dev/vc/:/dev/pty:/dev/tty:/dev/console:"
182 azarah 89 "/dev/shm/ngpt:/var/log/scrollkeeper.log:"
183     "/usr/tmp/conftest:/usr/lib/conftest:"
184     "/usr/lib32/conftest:/usr/lib64/conftest:"
185     "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf",
186 azarah 101 sandbox_info->home_dir, sandbox_info->home_dir,
187     (NULL != sandbox_info->portage_tmp_dir) ? sandbox_info->portage_tmp_dir : tmp_dir,
188     sandbox_info->tmp_dir, sandbox_info->var_tmp_dir,
189     "/tmp/:/var/tmp/");
190 azarah 89 }
191    
192 azarah 101 void get_sandbox_predict_envvar(char *buf, struct sandbox_info_t *sandbox_info)
193 azarah 89 {
194 ferringb 2 /* bzero out entire buffer then append trailing 0 */
195 azarah 93 memset(buf, 0, SB_BUF_LEN);
196 ferringb 2
197 azarah 89 /* these should go into make.globals later on */
198     snprintf(buf, SB_BUF_LEN, "%s/.:"
199     "/usr/lib/python2.0/:"
200     "/usr/lib/python2.1/:"
201     "/usr/lib/python2.2/:"
202     "/usr/lib/python2.3/:"
203     "/usr/lib/python2.4/:"
204     "/usr/lib/python2.5/:"
205 azarah 126 "/usr/lib/python3.0/:"
206     "/var/db/aliases.db:"
207     "/var/db/netgroup.db:"
208     "/var/db/netmasks.db:"
209     "/var/db/ethers.db:"
210     "/var/db/rpc.db:"
211     "/var/db/protocols.db:"
212     "/var/db/services.db:"
213     "/var/db/networks.db:"
214     "/var/db/hosts.db:"
215     "/var/db/group.db:"
216 azarah 131 "/var/db/passwd.db",
217 azarah 101 sandbox_info->home_dir);
218 azarah 89 }
219 ferringb 2
220 azarah 124 int sandbox_setenv(char **env, const char *name, const char *val) {
221 azarah 89 char **tmp_env = env;
222     char *tmp_string = NULL;
223    
224 azarah 100 /* XXX: We add the new variable to the end (no replacing). If this
225     * is changed, we need to fix sandbox_setup_environ() below */
226 azarah 89 while (NULL != *tmp_env)
227     tmp_env++;
228    
229     /* strlen(name) + strlen(val) + '=' + '\0' */
230 azarah 96 /* FIXME: Should probably free this at some stage - more neatness than
231     * a real leak that will cause issues. */
232 azarah 89 tmp_string = calloc(strlen(name) + strlen(val) + 2, sizeof(char *));
233     if (NULL == tmp_string) {
234 azarah 145 perror("sandbox: Out of memory (sandbox_setenv)");
235     exit(EXIT_FAILURE);
236 ferringb 2 }
237 azarah 89
238     snprintf(tmp_string, strlen(name) + strlen(val) + 2, "%s=%s",
239     name, val);
240     *tmp_env = tmp_string;
241    
242     return 0;
243 ferringb 2 }
244    
245 azarah 89 /* We setup the environment child side only to prevent issues with
246     * setting LD_PRELOAD parent side */
247 azarah 124 char **sandbox_setup_environ(struct sandbox_info_t *sandbox_info)
248 ferringb 2 {
249 azarah 89 int env_size = 0;
250 azarah 100 int have_ld_preload = 0;
251 azarah 89
252     char **new_environ;
253     char **env_ptr = environ;
254 azarah 124 char sandbox_write_envvar[SB_BUF_LEN];
255     char sandbox_predict_envvar[SB_BUF_LEN];
256 azarah 89 char *ld_preload_envvar = NULL;
257 azarah 100 char *orig_ld_preload_envvar = NULL;
258 ferringb 2
259 azarah 89 /* Unset these, as its easier than replacing when setting up our
260     * new environment below */
261     unsetenv(ENV_SANDBOX_LIB);
262     unsetenv(ENV_SANDBOX_BASHRC);
263     unsetenv(ENV_SANDBOX_LOG);
264     unsetenv(ENV_SANDBOX_DEBUG_LOG);
265    
266 azarah 100 if (NULL != getenv(ENV_LD_PRELOAD)) {
267     have_ld_preload = 1;
268     orig_ld_preload_envvar = getenv(ENV_LD_PRELOAD);
269    
270 azarah 96 /* FIXME: Should probably free this at some stage - more neatness
271     * than a real leak that will cause issues. */
272 azarah 100 ld_preload_envvar = calloc(strlen(orig_ld_preload_envvar) +
273 azarah 101 strlen(sandbox_info->sandbox_lib) + 2,
274     sizeof(char *));
275 azarah 89 if (NULL == ld_preload_envvar)
276     return NULL;
277 azarah 100 snprintf(ld_preload_envvar, strlen(orig_ld_preload_envvar) +
278 azarah 101 strlen(sandbox_info->sandbox_lib) + 2, "%s %s",
279     sandbox_info->sandbox_lib, orig_ld_preload_envvar);
280 azarah 89 } else {
281 azarah 96 /* FIXME: Should probably free this at some stage - more neatness
282     * than a real leak that will cause issues. */
283 azarah 101 ld_preload_envvar = strndup(sandbox_info->sandbox_lib,
284     strlen(sandbox_info->sandbox_lib));
285 azarah 89 if (NULL == ld_preload_envvar)
286     return NULL;
287     }
288 azarah 100 /* Do not unset this, as strange things might happen */
289     /* unsetenv(ENV_LD_PRELOAD); */
290 ferringb 2
291 azarah 89 while (NULL != *env_ptr) {
292     env_size++;
293     env_ptr++;
294     }
295 ferringb 2
296 azarah 96 /* FIXME: Should probably free this at some stage - more neatness than
297     * a real leak that will cause issues. */
298 azarah 89 new_environ = calloc((env_size + 15 + 1) * sizeof(char *), sizeof(char *));
299     if (NULL == new_environ)
300     return NULL;
301    
302     /* First add our new variables to the beginning - this is due to some
303     * weirdness that I cannot remember */
304 azarah 101 sandbox_setenv(new_environ, ENV_SANDBOX_LIB, sandbox_info->sandbox_lib);
305     sandbox_setenv(new_environ, ENV_SANDBOX_BASHRC, sandbox_info->sandbox_rc);
306     sandbox_setenv(new_environ, ENV_SANDBOX_LOG, sandbox_info->sandbox_log);
307     sandbox_setenv(new_environ, ENV_SANDBOX_DEBUG_LOG,
308     sandbox_info->sandbox_debug_log);
309 azarah 100 /* If LD_PRELOAD was not set, set it here, else do it below */
310     if (1 != have_ld_preload)
311     sandbox_setenv(new_environ, ENV_LD_PRELOAD, ld_preload_envvar);
312 azarah 89
313     if (!getenv(ENV_SANDBOX_DENY))
314     sandbox_setenv(new_environ, ENV_SANDBOX_DENY, LD_PRELOAD_FILE);
315    
316     if (!getenv(ENV_SANDBOX_READ))
317     sandbox_setenv(new_environ, ENV_SANDBOX_READ, "/");
318    
319 azarah 124 get_sandbox_write_envvar(sandbox_write_envvar, sandbox_info);
320 azarah 89 if (!getenv(ENV_SANDBOX_WRITE))
321     sandbox_setenv(new_environ, ENV_SANDBOX_WRITE, sandbox_write_envvar);
322    
323 azarah 124 get_sandbox_predict_envvar(sandbox_predict_envvar, sandbox_info);
324 azarah 89 if (!getenv(ENV_SANDBOX_PREDICT))
325     sandbox_setenv(new_environ, ENV_SANDBOX_PREDICT, sandbox_predict_envvar);
326    
327     /* This one should NEVER be set in ebuilds, as it is the one
328     * private thing libsandbox.so use to test if the sandbox
329     * should be active for this pid, or not.
330     *
331     * azarah (3 Aug 2002)
332     */
333    
334     sandbox_setenv(new_environ, "SANDBOX_ACTIVE", "armedandready");
335    
336     env_size = 0;
337     while (NULL != new_environ[env_size])
338     env_size++;
339    
340     /* Now add the rest */
341     env_ptr = environ;
342     while (NULL != *env_ptr) {
343 azarah 100 if ((1 == have_ld_preload) &&
344     (strstr(*env_ptr, LD_PRELOAD_EQ) == *env_ptr))
345     /* If LD_PRELOAD was set, and this is it in the original
346     * environment, replace it with our new copy */
347 azarah 101 /* XXX: The following works as it just add whatever as
348     * the last variable to nev_environ */
349 azarah 100 sandbox_setenv(new_environ, ENV_LD_PRELOAD,
350     ld_preload_envvar);
351     else
352     new_environ[env_size + (env_ptr - environ)] = *env_ptr;
353 azarah 89 env_ptr++;
354 ferringb 2 }
355 azarah 89
356     return new_environ;
357 ferringb 2 }
358    
359 azarah 145 int spawn_shell(char *argv_bash[], char *env[], int debug)
360 ferringb 2 {
361     int pid;
362     int status = 0;
363     int ret = 0;
364    
365     pid = fork();
366    
367     /* Child's process */
368     if (0 == pid) {
369 azarah 89 execve(argv_bash[0], argv_bash, env);
370 ferringb 2 return 0;
371     } else if (pid < 0) {
372 azarah 145 if (debug)
373     fprintf(stderr, "Process failed to spawn!\n");
374 ferringb 2 return 0;
375     }
376     ret = waitpid(pid, &status, 0);
377 azarah 145 if ((-1 == ret) || (status > 0)) {
378     if (debug)
379     fprintf(stderr, "Process returned with failed exit status!\n");
380 ferringb 2 return 0;
381 azarah 145 }
382 azarah 86
383 ferringb 2 return 1;
384     }
385    
386 azarah 30 int main(int argc, char **argv)
387 ferringb 2 {
388 azarah 101 int i = 0, success = 1;
389 ferringb 2 int sandbox_log_presence = 0;
390     long len;
391    
392 azarah 101 struct sandbox_info_t sandbox_info;
393 ferringb 2
394 azarah 89 char **sandbox_environ;
395 ferringb 2 char **argv_bash = NULL;
396    
397     char *run_str = "-c";
398    
399     /* Only print info if called with no arguments .... */
400     if (argc < 2)
401     print_debug = 1;
402    
403     if (print_debug)
404 azarah 30 printf("========================== Gentoo linux path sandbox ===========================\n");
405 ferringb 2
406     /* check if a sandbox is already running */
407     if (NULL != getenv(ENV_SANDBOX_ON)) {
408 azarah 30 fprintf(stderr, "Not launching a new sandbox instance\n");
409     fprintf(stderr, "Another one is already running in this process hierarchy.\n");
410 azarah 145 exit(EXIT_FAILURE);
411     }
412 ferringb 2
413 azarah 145 /* determine the location of all the sandbox support files */
414     if (print_debug)
415     printf("Detection of the support files.\n");
416 ferringb 2
417 azarah 145 if (-1 == sandbox_setup(&sandbox_info)) {
418 azarah 147 fprintf(stderr, "sandbox: Failed to setup sandbox.");
419 azarah 145 exit(EXIT_FAILURE);
420     }
421    
422     /* verify the existance of required files */
423     if (print_debug)
424     printf("Verification of the required files.\n");
425 ferringb 2
426     #ifndef SB_HAVE_64BIT_ARCH
427 azarah 145 if (0 >= exists(sandbox_info.sandbox_lib)) {
428     perror("sandbox: Could not open the sandbox library");
429     exit(EXIT_FAILURE);
430     }
431 ferringb 2 #endif
432 azarah 145 if (0 >= exists(sandbox_info.sandbox_rc)) {
433     perror("sandbox: Could not open the sandbox rc file");
434     exit(EXIT_FAILURE);
435     }
436 ferringb 2
437 azarah 145 /* set up the required environment variables */
438     if (print_debug)
439     printf("Setting up the required environment variables.\n");
440 ferringb 2
441 azarah 145 /* This one should not be child only, as we check above to see
442     * if we are already running (check sandbox_setup_environ).
443     * This needs to be set before calling sandbox_setup_environ(),
444     * else its not set for the child */
445     setenv(ENV_SANDBOX_ON, "1", 0);
446 azarah 91
447 azarah 145 /* Setup the child environment stuff */
448     sandbox_environ = sandbox_setup_environ(&sandbox_info);
449     if (NULL == sandbox_environ) {
450     perror("sandbox: Out of memory (environ)");
451     exit(EXIT_FAILURE);
452     }
453 ferringb 2
454 azarah 145 /* if the portage temp dir was present, cd into it */
455     if (NULL != sandbox_info.portage_tmp_dir)
456     chdir(sandbox_info.portage_tmp_dir);
457 ferringb 2
458 azarah 145 argv_bash = (char **)malloc(6 * sizeof(char *));
459     argv_bash[0] = strdup("/bin/bash");
460     argv_bash[1] = strdup("-rcfile");
461     argv_bash[2] = strdup(sandbox_info.sandbox_rc);
462 ferringb 2
463 azarah 145 if (argc < 2)
464     argv_bash[3] = NULL;
465     else
466     argv_bash[3] = strdup(run_str); /* "-c" */
467 ferringb 2
468 azarah 145 argv_bash[4] = NULL; /* strdup(run_arg); */
469     argv_bash[5] = NULL;
470 ferringb 2
471 azarah 145 if (argc >= 2) {
472     for (i = 1; i < argc; i++) {
473     if (NULL == argv_bash[4])
474     len = 0;
475     else
476     len = strlen(argv_bash[4]);
477 ferringb 2
478 azarah 145 argv_bash[4] = (char *)realloc(argv_bash[4],
479     (len + strlen(argv[i]) + 2) * sizeof(char));
480 ferringb 2
481 azarah 145 if (0 == len)
482     argv_bash[4][0] = 0;
483     if (1 != i)
484     strcat(argv_bash[4], " ");
485 ferringb 2
486 azarah 145 strcat(argv_bash[4], argv[i]);
487 ferringb 2 }
488 azarah 145 }
489 ferringb 2
490 azarah 145 /* set up the required signal handlers */
491     signal(SIGHUP, &stop);
492     signal(SIGINT, &stop);
493     signal(SIGQUIT, &stop);
494     signal(SIGTERM, &stop);
495 ferringb 2
496 azarah 145 /* STARTING PROTECTED ENVIRONMENT */
497     if (print_debug) {
498     printf("The protected environment has been started.\n");
499     printf("--------------------------------------------------------------------------------\n");
500     }
501 ferringb 2
502 azarah 145 if (print_debug)
503     printf("Process being started in forked instance.\n");
504 ferringb 2
505 azarah 145 /* Start Bash */
506     if (!spawn_shell(argv_bash, sandbox_environ, print_debug))
507     success = 0;
508 ferringb 2
509 azarah 145 /* Free bash stuff */
510     for (i = 0; i < 6; i++) {
511     if (argv_bash[i])
512     free(argv_bash[i]);
513     argv_bash[i] = NULL;
514     }
515     if (argv_bash)
516     free(argv_bash);
517     argv_bash = NULL;
518 ferringb 2
519 azarah 145 if (print_debug)
520     printf("Cleaning up sandbox process\n");
521 ferringb 2
522 azarah 145 if (print_debug) {
523     printf("========================== Gentoo linux path sandbox ===========================\n");
524     printf("The protected environment has been shut down.\n");
525     }
526 ferringb 2
527 azarah 145 if (1 == exists(sandbox_info.sandbox_log)) {
528     sandbox_log_presence = 1;
529     print_sandbox_log(sandbox_info.sandbox_log);
530     } else if (print_debug) {
531     printf("--------------------------------------------------------------------------------\n");
532     }
533 ferringb 2
534 azarah 145 if ((sandbox_log_presence) || (!success))
535     return 1;
536     else
537     return 0;
538 ferringb 2 }
539    
540 azarah 30 // vim:noexpandtab noai:cindent ai

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20