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

Diff of /trunk/src/sandbox.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 88 Revision 89
31#include <sys/wait.h> 31#include <sys/wait.h>
32#include <unistd.h> 32#include <unistd.h>
33#include <fcntl.h> 33#include <fcntl.h>
34#include "sandbox.h" 34#include "sandbox.h"
35 35
36#define SB_BUF_LEN 2048
37
36int preload_adaptable = 1; 38int preload_adaptable = 1;
37int cleaned_up = 0; 39int cleaned_up = 0;
38int print_debug = 0; 40int print_debug = 0;
39int stop_called = 0; 41int stop_called = 0;
40 42
232 } else { 234 } else {
233 fprintf(stderr, "Pid %d alreadly caught signal and is still cleaning up\n", getpid()); 235 fprintf(stderr, "Pid %d alreadly caught signal and is still cleaning up\n", getpid());
234 } 236 }
235} 237}
236 238
237void setenv_sandbox_write(char *home_dir, char *portage_tmp_dir, char *var_tmp_dir, char *tmp_dir) 239void get_sandbox_write_envvar(char *buf, char *home_dir, char *portage_tmp_dir, char *var_tmp_dir, char *tmp_dir)
238{ 240{
239 char buf[1024];
240
241 /* bzero out entire buffer then append trailing 0 */ 241 /* bzero out entire buffer then append trailing 0 */
242 memset(buf, 0, sizeof(buf)); 242 memset(buf, 0, SB_BUF_LEN + 1);
243 243
244 if (!getenv(ENV_SANDBOX_WRITE)) {
245 /* these could go into make.globals later on */ 244 /* these could go into make.globals later on */
246 snprintf(buf, sizeof(buf), 245 snprintf(buf, SB_BUF_LEN,
247 "%s:%s/.gconfd/lock:%s/.bash_history:", 246 "%s:%s/.gconfd/lock:%s/.bash_history:%s:%s:%s:%s",
248 "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:" 247 "/dev/zero:/dev/fd/:/dev/null:/dev/pts/:"
249 "/dev/vc/:/dev/pty:/dev/tty:/tmp/:" 248 "/dev/vc/:/dev/pty:/dev/tty:"
250 "/dev/shm/ngpt:/var/log/scrollkeeper.log:" 249 "/dev/shm/ngpt:/var/log/scrollkeeper.log:"
251 "/usr/tmp/conftest:/usr/lib/conftest:" 250 "/usr/tmp/conftest:/usr/lib/conftest:"
252 "/usr/lib32/conftest:/usr/lib64/conftest:" 251 "/usr/lib32/conftest:/usr/lib64/conftest:"
253 "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf", 252 "/usr/tmp/cf:/usr/lib/cf:/usr/lib32/cf:/usr/lib64/cf",
254 home_dir, home_dir); 253 home_dir, home_dir,
255 254 (NULL != portage_tmp_dir) ? portage_tmp_dir : tmp_dir,
256 if (NULL == portage_tmp_dir) { 255 tmp_dir, var_tmp_dir, "/tmp/:/var/tmp/");
257 strncat(buf, tmp_dir, sizeof(buf));
258 strncat(buf, ":", sizeof(buf));
259 strncat(buf, var_tmp_dir, sizeof(buf));
260 strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
261 } else {
262 strncat(buf, portage_tmp_dir, sizeof(buf));
263 strncat(buf, ":", sizeof(buf));
264 strncat(buf, tmp_dir, sizeof(buf));
265 strncat(buf, ":", sizeof(buf));
266 strncat(buf, var_tmp_dir, sizeof(buf));
267 strncat(buf, ":/tmp/:/var/tmp/", sizeof(buf));
268 }
269 buf[sizeof(buf) - 1] = '\0';
270 setenv(ENV_SANDBOX_WRITE, buf, 1);
271 }
272} 256}
273 257
274void setenv_sandbox_predict(char *home_dir) 258void get_sandbox_predict_envvar(char *buf, char *home_dir)
275{ 259{
276 char buf[1024]; 260 /* bzero out entire buffer then append trailing 0 */
261 memset(buf, 0, SB_BUF_LEN + 1);
277 262
278 memset(buf, 0, sizeof(buf));
279
280 if (!getenv(ENV_SANDBOX_PREDICT)) {
281 /* these should go into make.globals later on */ 263 /* these should go into make.globals later on */
282 snprintf(buf, sizeof(buf), "%s/.:" 264 snprintf(buf, SB_BUF_LEN, "%s/.:"
283 "/usr/lib/python2.0/:" 265 "/usr/lib/python2.0/:"
284 "/usr/lib/python2.1/:" 266 "/usr/lib/python2.1/:"
285 "/usr/lib/python2.2/:" 267 "/usr/lib/python2.2/:"
286 "/usr/lib/python2.3/:" 268 "/usr/lib/python2.3/:"
287 "/usr/lib/python2.4/:" 269 "/usr/lib/python2.4/:"
288 "/usr/lib/python2.5/:" 270 "/usr/lib/python2.5/:"
289 "/usr/lib/python3.0/:", 271 "/usr/lib/python3.0/:",
290 home_dir); 272 home_dir);
273}
291 274
292 buf[sizeof(buf) - 1] = '\0'; 275int sandbox_setenv(char **env, char *name, char *val) {
276 char **tmp_env = env;
277 char *tmp_string = NULL;
278
279 while (NULL != *tmp_env)
280 tmp_env++;
281
282 /* strlen(name) + strlen(val) + '=' + '\0' */
283 tmp_string = calloc(strlen(name) + strlen(val) + 2, sizeof(char *));
284 if (NULL == tmp_string) {
285 perror(">>> out of memory (sandbox_setenv)");
286 exit(1);
287 }
288
289 snprintf(tmp_string, strlen(name) + strlen(val) + 2, "%s=%s",
290 name, val);
291 *tmp_env = tmp_string;
292
293 return 0;
294}
295
296/* We setup the environment child side only to prevent issues with
297 * setting LD_PRELOAD parent side */
298char **sandbox_setup_environ(char *sandbox_dir, char *sandbox_lib, char *sandbox_rc, char *sandbox_log,
299 char *sandbox_debug_log, char *sandbox_write_envvar, char *sandbox_predict_envvar)
300{
301 int env_size = 0;
302
303 char **new_environ;
304 char **env_ptr = environ;
305 char *ld_preload_envvar = NULL;
306
307 /* Unset these, as its easier than replacing when setting up our
308 * new environment below */
309 unsetenv(ENV_SANDBOX_DIR);
310 unsetenv(ENV_SANDBOX_LIB);
311 unsetenv(ENV_SANDBOX_BASHRC);
312 unsetenv(ENV_SANDBOX_LOG);
313 unsetenv(ENV_SANDBOX_DEBUG_LOG);
314
315 if (NULL != getenv("LD_PRELOAD")) {
316 ld_preload_envvar = malloc(strlen(getenv("LD_PRELOAD")) +
317 strlen(sandbox_lib) + 2);
318 if (NULL == ld_preload_envvar)
319 return NULL;
320 strncpy(ld_preload_envvar, sandbox_lib, strlen(sandbox_lib));
321 strncat(ld_preload_envvar, " ", 1);
322 strncat(ld_preload_envvar, getenv("LD_PRELOAD"),
323 strlen(getenv("LD_PRELOAD")));
324 } else {
325 ld_preload_envvar = strndup(sandbox_lib, strlen(sandbox_lib));
326 if (NULL == ld_preload_envvar)
327 return NULL;
328 }
329 unsetenv("LD_PRELOAD");
330
331 while (NULL != *env_ptr) {
332 env_size++;
333 env_ptr++;
334 }
335
336 new_environ = calloc((env_size + 15 + 1) * sizeof(char *), sizeof(char *));
337 if (NULL == new_environ)
338 return NULL;
339
340 /* First add our new variables to the beginning - this is due to some
341 * weirdness that I cannot remember */
342 sandbox_setenv(new_environ, ENV_SANDBOX_DIR, sandbox_dir);
343 sandbox_setenv(new_environ, ENV_SANDBOX_LIB, sandbox_lib);
344 sandbox_setenv(new_environ, ENV_SANDBOX_BASHRC, sandbox_rc);
345 sandbox_setenv(new_environ, ENV_SANDBOX_LOG, sandbox_log);
346 sandbox_setenv(new_environ, ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log);
347 sandbox_setenv(new_environ, "LD_PRELOAD", ld_preload_envvar);
348
349 if (!getenv(ENV_SANDBOX_DENY))
350 sandbox_setenv(new_environ, ENV_SANDBOX_DENY, LD_PRELOAD_FILE);
351
352 if (!getenv(ENV_SANDBOX_READ))
353 sandbox_setenv(new_environ, ENV_SANDBOX_READ, "/");
354
355 if (!getenv(ENV_SANDBOX_WRITE))
356 sandbox_setenv(new_environ, ENV_SANDBOX_WRITE, sandbox_write_envvar);
357
293 setenv(ENV_SANDBOX_PREDICT, buf, 1); 358 if (!getenv(ENV_SANDBOX_PREDICT))
294 } 359 sandbox_setenv(new_environ, ENV_SANDBOX_PREDICT, sandbox_predict_envvar);
295}
296 360
361 /* This one should NEVER be set in ebuilds, as it is the one
362 * private thing libsandbox.so use to test if the sandbox
363 * should be active for this pid, or not.
364 *
365 * azarah (3 Aug 2002)
366 */
367
368 sandbox_setenv(new_environ, "SANDBOX_ACTIVE", "armedandready");
369
370 env_size = 0;
371 while (NULL != new_environ[env_size])
372 env_size++;
373
374 /* Now add the rest */
375 env_ptr = environ;
376 while (NULL != *env_ptr) {
377 new_environ[env_size + (env_ptr - environ)] = *env_ptr;
378 env_ptr++;
379 }
380
381 return new_environ;
382}
383
297int spawn_shell(char *argv_bash[]) 384int spawn_shell(char *argv_bash[], char *env[])
298{ 385{
299 int pid; 386 int pid;
300 int status = 0; 387 int status = 0;
301 int ret = 0; 388 int ret = 0;
302 389
303 pid = fork(); 390 pid = fork();
304 391
305 /* Child's process */ 392 /* Child's process */
306 if (0 == pid) { 393 if (0 == pid) {
307 execv(argv_bash[0], argv_bash); 394 execve(argv_bash[0], argv_bash, env);
308 return 0; 395 return 0;
309 } else if (pid < 0) { 396 } else if (pid < 0) {
310 return 0; 397 return 0;
311 } 398 }
312 ret = waitpid(pid, &status, 0); 399 ret = waitpid(pid, &status, 0);
333 char tmp_dir[PATH_MAX]; 420 char tmp_dir[PATH_MAX];
334 char sandbox_log[255]; 421 char sandbox_log[255];
335 char sandbox_debug_log[255]; 422 char sandbox_debug_log[255];
336 char sandbox_dir[255]; 423 char sandbox_dir[255];
337 char sandbox_lib[255]; 424 char sandbox_lib[255];
425 char sandbox_write_envvar[SB_BUF_LEN + 1];
426 char sandbox_predict_envvar[SB_BUF_LEN + 1];
427 char **sandbox_environ;
338 char *sandbox_pids_file; 428 char *sandbox_pids_file;
339 char sandbox_rc[255]; 429 char sandbox_rc[255];
340 char pid_string[255]; 430 char pid_string[255];
341 char **argv_bash = NULL; 431 char **argv_bash = NULL;
342 432
411 strncpy(sandbox_log, tmp_string, 254); 501 strncpy(sandbox_log, tmp_string, 254);
412 if (tmp_string) 502 if (tmp_string)
413 free(tmp_string); 503 free(tmp_string);
414 tmp_string = NULL; 504 tmp_string = NULL;
415 505
416 setenv(ENV_SANDBOX_LOG, sandbox_log, 1);
417
418 sprintf(pid_string, "%d", getpid()); 506 sprintf(pid_string, "%d", getpid());
419 snprintf(sandbox_debug_log, sizeof(sandbox_debug_log), "%s%s%s", 507 snprintf(sandbox_debug_log, sizeof(sandbox_debug_log), "%s%s%s",
420 DEBUG_LOG_FILE_PREFIX, pid_string, LOG_FILE_EXT); 508 DEBUG_LOG_FILE_PREFIX, pid_string, LOG_FILE_EXT);
421 setenv(ENV_SANDBOX_DEBUG_LOG, sandbox_debug_log, 1);
422 509
423 home_dir = getenv("HOME"); 510 home_dir = getenv("HOME");
424 if (!home_dir) { 511 if (!home_dir) {
425 home_dir = "/tmp"; 512 home_dir = "/tmp";
426 setenv("HOME", home_dir, 1); 513 setenv("HOME", home_dir, 1);
439 if (NULL == realpath("/tmp", tmp_dir)) { 526 if (NULL == realpath("/tmp", tmp_dir)) {
440 perror(">>> get tmp_dir"); 527 perror(">>> get tmp_dir");
441 exit(1); 528 exit(1);
442 } 529 }
443 530
444 setenv(ENV_SANDBOX_DIR, sandbox_dir, 1); 531 /* Setup the environment stuff */
445 setenv(ENV_SANDBOX_LIB, sandbox_lib, 1); 532 get_sandbox_write_envvar(sandbox_write_envvar, home_dir,
446 setenv(ENV_SANDBOX_BASHRC, sandbox_rc, 1); 533 portage_tmp_dir, var_tmp_dir, tmp_dir);
447 if ((NULL != getenv("LD_PRELOAD")) && 534 get_sandbox_predict_envvar(sandbox_predict_envvar, home_dir);
448 /* FIXME: for now, do not use current LD_PRELOAD if 535 sandbox_environ = sandbox_setup_environ(sandbox_dir, sandbox_lib,
449 * it contains libtsocks, as it breaks sandbox, bug #91541. 536 sandbox_rc, sandbox_log, sandbox_debug_log,
450 */ 537 sandbox_write_envvar, sandbox_predict_envvar);
451 (NULL == strstr(getenv("LD_PRELOAD"), "libtsocks"))) { 538 if (NULL == sandbox_environ) {
452 tmp_string = malloc(strlen(getenv("LD_PRELOAD")) +
453 strlen(sandbox_lib) + 2);
454 if (NULL == tmp_string) {
455 perror(">>> Out of memory (LD_PRELOAD)"); 539 perror(">>> out of memory (environ)");
456 exit(1); 540 exit(1);
457 } 541 }
458 strncpy(tmp_string, sandbox_lib, strlen(sandbox_lib));
459 strncat(tmp_string, " ", 1);
460 strncat(tmp_string, getenv("LD_PRELOAD"), strlen(getenv("LD_PRELOAD")));
461 setenv("LD_PRELOAD", tmp_string, 1);
462 free(tmp_string);
463 } else {
464 setenv("LD_PRELOAD", sandbox_lib, 1);
465 }
466 542
467 if (!getenv(ENV_SANDBOX_DENY)) 543 /* This one should not be child only, as we check above to see
468 setenv(ENV_SANDBOX_DENY, LD_PRELOAD_FILE, 1); 544 * if we are already running (check sandbox_setup_environ) */
469
470 if (!getenv(ENV_SANDBOX_READ))
471 setenv(ENV_SANDBOX_READ, "/", 1);
472
473 /* Set up Sandbox Write path */
474 setenv_sandbox_write(home_dir, portage_tmp_dir, var_tmp_dir, tmp_dir);
475 setenv_sandbox_predict(home_dir);
476
477 setenv(ENV_SANDBOX_ON, "1", 0); 545 setenv(ENV_SANDBOX_ON, "1", 0);
478 546
479 /* if the portage temp dir was present, cd into it */ 547 /* if the portage temp dir was present, cd into it */
480 if (NULL != portage_tmp_dir) 548 if (NULL != portage_tmp_dir)
481 chdir(portage_tmp_dir); 549 chdir(portage_tmp_dir);
498 if (NULL == argv_bash[4]) 566 if (NULL == argv_bash[4])
499 len = 0; 567 len = 0;
500 else 568 else
501 len = strlen(argv_bash[4]); 569 len = strlen(argv_bash[4]);
502 570
503 argv_bash[4] = (char *)realloc(argv_bash[4], (len + strlen(argv[i]) + 2) * sizeof(char)); 571 argv_bash[4] = (char *)realloc(argv_bash[4],
572 (len + strlen(argv[i]) + 2) * sizeof(char));
504 573
505 if (0 == len) 574 if (0 == len)
506 argv_bash[4][0] = 0; 575 argv_bash[4][0] = 0;
507 if (1 != i) 576 if (1 != i)
508 strcat(argv_bash[4], " "); 577 strcat(argv_bash[4], " ");
514 /* set up the required signal handlers */ 583 /* set up the required signal handlers */
515 signal(SIGHUP, &stop); 584 signal(SIGHUP, &stop);
516 signal(SIGINT, &stop); 585 signal(SIGINT, &stop);
517 signal(SIGQUIT, &stop); 586 signal(SIGQUIT, &stop);
518 signal(SIGTERM, &stop); 587 signal(SIGTERM, &stop);
519
520 /* this one should NEVER be set in ebuilds, as it is the one
521 * private thing libsandbox.so use to test if the sandbox
522 * should be active for this pid, or not.
523 *
524 * azarah (3 Aug 2002)
525 */
526
527 setenv("SANDBOX_ACTIVE", "armedandready", 1);
528 588
529 /* Load our PID into PIDs file */ 589 /* Load our PID into PIDs file */
530 success = 1; 590 success = 1;
531 if (file_exist(sandbox_pids_file, 1) < 0) { 591 if (file_exist(sandbox_pids_file, 1) < 0) {
532 success = 0; 592 success = 0;
581 641
582 if (print_debug) 642 if (print_debug)
583 printf("Shell being started in forked process.\n"); 643 printf("Shell being started in forked process.\n");
584 644
585 /* Start Bash */ 645 /* Start Bash */
586 if (!spawn_shell(argv_bash)) { 646 if (!spawn_shell(argv_bash, sandbox_environ)) {
587 if (print_debug) 647 if (print_debug)
588 fprintf(stderr, ">>> shell process failed to spawn\n"); 648 fprintf(stderr, ">>> shell process failed to spawn\n");
589 success = 0; 649 success = 0;
590 } 650 }
591 651

Legend:
Removed from v.88  
changed lines
  Added in v.89

  ViewVC Help
Powered by ViewVC 1.1.20