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

Contents of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20