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

Contents of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.20