| … | |
… | |
| 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 | |
| 36 | int preload_adaptable = 1; |
38 | int preload_adaptable = 1; |
| 37 | int cleaned_up = 0; |
39 | int cleaned_up = 0; |
| 38 | int print_debug = 0; |
40 | int print_debug = 0; |
| 39 | int stop_called = 0; |
41 | int 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 | |
| 237 | void setenv_sandbox_write(char *home_dir, char *portage_tmp_dir, char *var_tmp_dir, char *tmp_dir) |
239 | void 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 | |
| 274 | void setenv_sandbox_predict(char *home_dir) |
258 | void 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'; |
275 | int 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 */ |
|
|
298 | char **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 | |
| 297 | int spawn_shell(char *argv_bash[]) |
384 | int 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 | |