diff options
Diffstat (limited to 'src/firejail/profile.c')
-rw-r--r-- | src/firejail/profile.c | 380 |
1 files changed, 353 insertions, 27 deletions
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 6ded0ca2f..0fd45d1ef 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -105,7 +105,12 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
105 | // mkdir | 105 | // mkdir |
106 | if (strncmp(ptr, "mkdir ", 6) == 0) { | 106 | if (strncmp(ptr, "mkdir ", 6) == 0) { |
107 | fs_mkdir(ptr + 6); | 107 | fs_mkdir(ptr + 6); |
108 | return 0; | 108 | return 1; // process mkdir again while applying blacklists |
109 | } | ||
110 | // mkfile | ||
111 | if (strncmp(ptr, "mkfile ", 7) == 0) { | ||
112 | fs_mkfile(ptr + 7); | ||
113 | return 1; // process mkfile again while applying blacklists | ||
109 | } | 114 | } |
110 | // sandbox name | 115 | // sandbox name |
111 | else if (strncmp(ptr, "name ", 5) == 0) { | 116 | else if (strncmp(ptr, "name ", 5) == 0) { |
@@ -131,6 +136,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
131 | 136 | ||
132 | return 0; | 137 | return 0; |
133 | } | 138 | } |
139 | else if (strcmp(ptr, "nonewprivs") == 0) { | ||
140 | arg_nonewprivs = 1; | ||
141 | return 0; | ||
142 | } | ||
134 | else if (strcmp(ptr, "seccomp") == 0) { | 143 | else if (strcmp(ptr, "seccomp") == 0) { |
135 | #ifdef HAVE_SECCOMP | 144 | #ifdef HAVE_SECCOMP |
136 | if (checkcfg(CFG_SECCOMP)) | 145 | if (checkcfg(CFG_SECCOMP)) |
@@ -160,6 +169,22 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
160 | arg_private = 1; | 169 | arg_private = 1; |
161 | return 0; | 170 | return 0; |
162 | } | 171 | } |
172 | if (strncmp(ptr, "private-home ", 13) == 0) { | ||
173 | #ifdef HAVE_PRIVATE_HOME | ||
174 | if (checkcfg(CFG_PRIVATE_HOME)) { | ||
175 | cfg.home_private_keep = ptr + 13; | ||
176 | fs_check_home_list(); | ||
177 | arg_private = 1; | ||
178 | } | ||
179 | else | ||
180 | fprintf(stderr, "Warning: private-home is disabled in Firejail configuration file\n"); | ||
181 | #endif | ||
182 | return 0; | ||
183 | } | ||
184 | else if (strcmp(ptr, "allusers") == 0) { | ||
185 | arg_allusers = 1; | ||
186 | return 0; | ||
187 | } | ||
163 | else if (strcmp(ptr, "private-dev") == 0) { | 188 | else if (strcmp(ptr, "private-dev") == 0) { |
164 | arg_private_dev = 1; | 189 | arg_private_dev = 1; |
165 | return 0; | 190 | return 0; |
@@ -174,7 +199,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
174 | } | 199 | } |
175 | else if (strcmp(ptr, "nosound") == 0) { | 200 | else if (strcmp(ptr, "nosound") == 0) { |
176 | arg_nosound = 1; | 201 | arg_nosound = 1; |
177 | arg_private_dev = 1; | 202 | return 0; |
203 | } | ||
204 | else if (strcmp(ptr, "no3d") == 0) { | ||
205 | arg_no3d = 1; | ||
178 | return 0; | 206 | return 0; |
179 | } | 207 | } |
180 | else if (strcmp(ptr, "netfilter") == 0) { | 208 | else if (strcmp(ptr, "netfilter") == 0) { |
@@ -274,6 +302,29 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
274 | return 0; | 302 | return 0; |
275 | } | 303 | } |
276 | 304 | ||
305 | else if (strncmp(ptr, "veth-name ", 10) == 0) { | ||
306 | #ifdef HAVE_NETWORK | ||
307 | if (checkcfg(CFG_NETWORK)) { | ||
308 | Bridge *br = last_bridge_configured(); | ||
309 | if (br == NULL) { | ||
310 | fprintf(stderr, "Error: no network device configured\n"); | ||
311 | exit(1); | ||
312 | } | ||
313 | |||
314 | br->veth_name = strdup(ptr + 10); | ||
315 | if (br->veth_name == NULL) | ||
316 | errExit("strdup"); | ||
317 | if (*br->veth_name == '\0') { | ||
318 | fprintf(stderr, "Error: no veth-name configured\n"); | ||
319 | exit(1); | ||
320 | } | ||
321 | } | ||
322 | else | ||
323 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
324 | #endif | ||
325 | return 0; | ||
326 | } | ||
327 | |||
277 | else if (strncmp(ptr, "iprange ", 8) == 0) { | 328 | else if (strncmp(ptr, "iprange ", 8) == 0) { |
278 | #ifdef HAVE_NETWORK | 329 | #ifdef HAVE_NETWORK |
279 | if (checkcfg(CFG_NETWORK)) { | 330 | if (checkcfg(CFG_NETWORK)) { |
@@ -319,11 +370,145 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
319 | return 0; | 370 | return 0; |
320 | } | 371 | } |
321 | 372 | ||
322 | 373 | ||
374 | else if (strncmp(ptr, "mac ", 4) == 0) { | ||
375 | #ifdef HAVE_NETWORK | ||
376 | if (checkcfg(CFG_NETWORK)) { | ||
377 | Bridge *br = last_bridge_configured(); | ||
378 | if (br == NULL) { | ||
379 | fprintf(stderr, "Error: no network device configured\n"); | ||
380 | exit(1); | ||
381 | } | ||
382 | |||
383 | if (mac_not_zero(br->macsandbox)) { | ||
384 | fprintf(stderr, "Error: cannot configure the MAC address twice for the same interface\n"); | ||
385 | exit(1); | ||
386 | } | ||
387 | |||
388 | // read the address | ||
389 | if (atomac(ptr + 4, br->macsandbox)) { | ||
390 | fprintf(stderr, "Error: invalid MAC address\n"); | ||
391 | exit(1); | ||
392 | } | ||
393 | } | ||
394 | else | ||
395 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
396 | #endif | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | else if (strncmp(ptr, "mtu ", 4) == 0) { | ||
401 | #ifdef HAVE_NETWORK | ||
402 | if (checkcfg(CFG_NETWORK)) { | ||
403 | Bridge *br = last_bridge_configured(); | ||
404 | if (br == NULL) { | ||
405 | fprintf(stderr, "Error: no network device configured\n"); | ||
406 | exit(1); | ||
407 | } | ||
408 | |||
409 | if (sscanf(ptr + 4, "%d", &br->mtu) != 1 || br->mtu < 576 || br->mtu > 9198) { | ||
410 | fprintf(stderr, "Error: invalid mtu value\n"); | ||
411 | exit(1); | ||
412 | } | ||
413 | } | ||
414 | else | ||
415 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
416 | #endif | ||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | else if (strncmp(ptr, "ip ", 3) == 0) { | ||
421 | #ifdef HAVE_NETWORK | ||
422 | if (checkcfg(CFG_NETWORK)) { | ||
423 | Bridge *br = last_bridge_configured(); | ||
424 | if (br == NULL) { | ||
425 | fprintf(stderr, "Error: no network device configured\n"); | ||
426 | exit(1); | ||
427 | } | ||
428 | if (br->arg_ip_none || br->ipsandbox) { | ||
429 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); | ||
430 | exit(1); | ||
431 | } | ||
432 | |||
433 | // configure this IP address for the last bridge defined | ||
434 | if (strcmp(ptr + 3, "none") == 0) | ||
435 | br->arg_ip_none = 1; | ||
436 | else { | ||
437 | if (atoip(ptr + 3, &br->ipsandbox)) { | ||
438 | fprintf(stderr, "Error: invalid IP address\n"); | ||
439 | exit(1); | ||
440 | } | ||
441 | } | ||
442 | } | ||
443 | else | ||
444 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
445 | #endif | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | else if (strncmp(ptr, "ip6 ", 4) == 0) { | ||
450 | #ifdef HAVE_NETWORK | ||
451 | if (checkcfg(CFG_NETWORK)) { | ||
452 | Bridge *br = last_bridge_configured(); | ||
453 | if (br == NULL) { | ||
454 | fprintf(stderr, "Error: no network device configured\n"); | ||
455 | exit(1); | ||
456 | } | ||
457 | if (br->arg_ip_none || br->ip6sandbox) { | ||
458 | fprintf(stderr, "Error: cannot configure the IP address twice for the same interface\n"); | ||
459 | exit(1); | ||
460 | } | ||
461 | |||
462 | // configure this IP address for the last bridge defined | ||
463 | // todo: verify ipv6 syntax | ||
464 | br->ip6sandbox = ptr + 4; | ||
465 | // if (atoip(argv[i] + 5, &br->ipsandbox)) { | ||
466 | // fprintf(stderr, "Error: invalid IP address\n"); | ||
467 | // exit(1); | ||
468 | // } | ||
469 | |||
470 | } | ||
471 | else | ||
472 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
473 | #endif | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | else if (strncmp(ptr, "defaultgw ", 10) == 0) { | ||
478 | #ifdef HAVE_NETWORK | ||
479 | if (checkcfg(CFG_NETWORK)) { | ||
480 | if (atoip(ptr + 10, &cfg.defaultgw)) { | ||
481 | fprintf(stderr, "Error: invalid IP address\n"); | ||
482 | exit(1); | ||
483 | } | ||
484 | } | ||
485 | else | ||
486 | fprintf(stderr, "Warning: networking features are disabled in Firejail configuration file\n"); | ||
487 | #endif | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | if (strcmp(ptr, "apparmor") == 0) { | ||
492 | #ifdef HAVE_APPARMOR | ||
493 | arg_apparmor = 1; | ||
494 | #endif | ||
495 | return 0; | ||
496 | } | ||
497 | |||
323 | if (strncmp(ptr, "protocol ", 9) == 0) { | 498 | if (strncmp(ptr, "protocol ", 9) == 0) { |
324 | #ifdef HAVE_SECCOMP | 499 | #ifdef HAVE_SECCOMP |
325 | if (checkcfg(CFG_SECCOMP)) | 500 | if (checkcfg(CFG_SECCOMP)) { |
326 | protocol_store(ptr + 9); | 501 | if (cfg.protocol) { |
502 | if (!arg_quiet) | ||
503 | fprintf(stderr, "Warning: a protocol list is present, the new list \"%s\" will not be installed\n", ptr + 9); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | // store list | ||
508 | cfg.protocol = strdup(ptr + 9); | ||
509 | if (!cfg.protocol) | ||
510 | errExit("strdup"); | ||
511 | } | ||
327 | else | 512 | else |
328 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); | 513 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); |
329 | #endif | 514 | #endif |
@@ -331,7 +516,11 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
331 | } | 516 | } |
332 | 517 | ||
333 | if (strncmp(ptr, "env ", 4) == 0) { | 518 | if (strncmp(ptr, "env ", 4) == 0) { |
334 | env_store(ptr + 4); | 519 | env_store(ptr + 4, SETENV); |
520 | return 0; | ||
521 | } | ||
522 | if (strncmp(ptr, "rmenv ", 6) == 0) { | ||
523 | env_store(ptr + 6, RMENV); | ||
335 | return 0; | 524 | return 0; |
336 | } | 525 | } |
337 | 526 | ||
@@ -340,9 +529,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
340 | #ifdef HAVE_SECCOMP | 529 | #ifdef HAVE_SECCOMP |
341 | if (checkcfg(CFG_SECCOMP)) { | 530 | if (checkcfg(CFG_SECCOMP)) { |
342 | arg_seccomp = 1; | 531 | arg_seccomp = 1; |
343 | cfg.seccomp_list = strdup(ptr + 8); | 532 | cfg.seccomp_list = seccomp_check_list(ptr + 8); |
344 | if (!cfg.seccomp_list) | ||
345 | errExit("strdup"); | ||
346 | } | 533 | } |
347 | else | 534 | else |
348 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); | 535 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); |
@@ -356,9 +543,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
356 | #ifdef HAVE_SECCOMP | 543 | #ifdef HAVE_SECCOMP |
357 | if (checkcfg(CFG_SECCOMP)) { | 544 | if (checkcfg(CFG_SECCOMP)) { |
358 | arg_seccomp = 1; | 545 | arg_seccomp = 1; |
359 | cfg.seccomp_list_drop = strdup(ptr + 13); | 546 | cfg.seccomp_list_drop = seccomp_check_list(ptr + 13); |
360 | if (!cfg.seccomp_list_drop) | ||
361 | errExit("strdup"); | ||
362 | } | 547 | } |
363 | else | 548 | else |
364 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); | 549 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); |
@@ -371,9 +556,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
371 | #ifdef HAVE_SECCOMP | 556 | #ifdef HAVE_SECCOMP |
372 | if (checkcfg(CFG_SECCOMP)) { | 557 | if (checkcfg(CFG_SECCOMP)) { |
373 | arg_seccomp = 1; | 558 | arg_seccomp = 1; |
374 | cfg.seccomp_list_keep= strdup(ptr + 13); | 559 | cfg.seccomp_list_keep= seccomp_check_list(ptr + 13); |
375 | if (!cfg.seccomp_list_keep) | ||
376 | errExit("strdup"); | ||
377 | } | 560 | } |
378 | else | 561 | else |
379 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); | 562 | fprintf(stderr, "Warning: user seccomp feature is disabled in Firejail configuration file\n"); |
@@ -387,7 +570,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
387 | arg_caps_list = strdup(ptr + 10); | 570 | arg_caps_list = strdup(ptr + 10); |
388 | if (!arg_caps_list) | 571 | if (!arg_caps_list) |
389 | errExit("strdup"); | 572 | errExit("strdup"); |
390 | // verify seccomp list and exit if problems | 573 | // verify caps list and exit if problems |
391 | if (caps_check_list(arg_caps_list, NULL)) | 574 | if (caps_check_list(arg_caps_list, NULL)) |
392 | exit(1); | 575 | exit(1); |
393 | return 0; | 576 | return 0; |
@@ -399,7 +582,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
399 | arg_caps_list = strdup(ptr + 10); | 582 | arg_caps_list = strdup(ptr + 10); |
400 | if (!arg_caps_list) | 583 | if (!arg_caps_list) |
401 | errExit("strdup"); | 584 | errExit("strdup"); |
402 | // verify seccomp list and exit if problems | 585 | // verify caps list and exit if problems |
403 | if (caps_check_list(arg_caps_list, NULL)) | 586 | if (caps_check_list(arg_caps_list, NULL)) |
404 | exit(1); | 587 | exit(1); |
405 | return 0; | 588 | return 0; |
@@ -441,6 +624,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
441 | // nice value | 624 | // nice value |
442 | if (strncmp(ptr, "nice ", 4) == 0) { | 625 | if (strncmp(ptr, "nice ", 4) == 0) { |
443 | cfg.nice = atoi(ptr + 5); | 626 | cfg.nice = atoi(ptr + 5); |
627 | if (getuid() != 0 &&cfg.nice < 0) | ||
628 | cfg.nice = 0; | ||
444 | arg_nice = 1; | 629 | arg_nice = 1; |
445 | return 0; | 630 | return 0; |
446 | } | 631 | } |
@@ -451,6 +636,22 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
451 | return 0; | 636 | return 0; |
452 | } | 637 | } |
453 | 638 | ||
639 | // writable-etc | ||
640 | if (strcmp(ptr, "writable-etc") == 0) { | ||
641 | if (cfg.etc_private_keep) { | ||
642 | fprintf(stderr, "Error: private-etc and writable-etc are mutually exclusive\n"); | ||
643 | exit(1); | ||
644 | } | ||
645 | arg_writable_etc = 1; | ||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | // writable-var | ||
650 | if (strcmp(ptr, "writable-var") == 0) { | ||
651 | arg_writable_var = 1; | ||
652 | return 0; | ||
653 | } | ||
654 | |||
454 | // private directory | 655 | // private directory |
455 | if (strncmp(ptr, "private ", 8) == 0) { | 656 | if (strncmp(ptr, "private ", 8) == 0) { |
456 | cfg.home_private = ptr + 8; | 657 | cfg.home_private = ptr + 8; |
@@ -459,16 +660,85 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
459 | return 0; | 660 | return 0; |
460 | } | 661 | } |
461 | 662 | ||
663 | if (strcmp(ptr, "x11 none") == 0) { | ||
664 | arg_x11_block = 1; | ||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | if (strcmp(ptr, "x11 xephyr") == 0) { | ||
669 | #ifdef HAVE_X11 | ||
670 | if (checkcfg(CFG_X11)) { | ||
671 | char *x11env = getenv("FIREJAIL_X11"); | ||
672 | if (x11env && strcmp(x11env, "yes") == 0) { | ||
673 | mask_x11_abstract_socket = 1; | ||
674 | return 0; | ||
675 | } | ||
676 | else { | ||
677 | // start x11 | ||
678 | x11_start_xephyr(cfg.original_argc, cfg.original_argv); | ||
679 | exit(0); | ||
680 | } | ||
681 | } | ||
682 | #endif | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | if (strcmp(ptr, "x11 xorg") == 0) { | ||
687 | #ifdef HAVE_X11 | ||
688 | if (checkcfg(CFG_X11)) | ||
689 | arg_x11_xorg = 1; | ||
690 | else { | ||
691 | fprintf(stderr, "Error: --x11 feature is disabled in Firejail configuration file\n"); | ||
692 | return 0; | ||
693 | } | ||
694 | #endif | ||
695 | return 0; | ||
696 | } | ||
697 | if (strcmp(ptr, "x11 xpra") == 0) { | ||
698 | #ifdef HAVE_X11 | ||
699 | if (checkcfg(CFG_X11)) { | ||
700 | char *x11env = getenv("FIREJAIL_X11"); | ||
701 | if (x11env && strcmp(x11env, "yes") == 0) { | ||
702 | mask_x11_abstract_socket = 1; | ||
703 | return 0; | ||
704 | } | ||
705 | else { | ||
706 | // start x11 | ||
707 | x11_start_xpra(cfg.original_argc, cfg.original_argv); | ||
708 | exit(0); | ||
709 | } | ||
710 | } | ||
711 | #endif | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | if (strcmp(ptr, "x11") == 0) { | ||
716 | #ifdef HAVE_X11 | ||
717 | if (checkcfg(CFG_X11)) { | ||
718 | char *x11env = getenv("FIREJAIL_X11"); | ||
719 | if (x11env && strcmp(x11env, "yes") == 0) { | ||
720 | mask_x11_abstract_socket = 1; | ||
721 | return 0; | ||
722 | } | ||
723 | else { | ||
724 | // start x11 | ||
725 | x11_start(cfg.original_argc, cfg.original_argv); | ||
726 | exit(0); | ||
727 | } | ||
728 | } | ||
729 | #endif | ||
730 | return 0; | ||
731 | } | ||
732 | |||
462 | // private /etc list of files and directories | 733 | // private /etc list of files and directories |
463 | if (strncmp(ptr, "private-etc ", 12) == 0) { | 734 | if (strncmp(ptr, "private-etc ", 12) == 0) { |
735 | if (arg_writable_etc) { | ||
736 | fprintf(stderr, "Error: --private-etc and --writable-etc are mutually exclusive\n"); | ||
737 | exit(1); | ||
738 | } | ||
464 | cfg.etc_private_keep = ptr + 12; | 739 | cfg.etc_private_keep = ptr + 12; |
465 | fs_check_etc_list(); | 740 | fs_check_etc_list(); |
466 | if (*cfg.etc_private_keep != '\0') | 741 | arg_private_etc = 1; |
467 | arg_private_etc = 1; | ||
468 | else { | ||
469 | arg_private_etc = 0; | ||
470 | fprintf(stderr, "Warning: private-etc disabled, no file found\n"); | ||
471 | } | ||
472 | 742 | ||
473 | return 0; | 743 | return 0; |
474 | } | 744 | } |
@@ -569,6 +839,30 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
569 | return 0; | 839 | return 0; |
570 | } | 840 | } |
571 | 841 | ||
842 | if (strncmp(ptr, "join-or-start ", 14) == 0) { | ||
843 | // try to join by name only | ||
844 | pid_t pid; | ||
845 | if (!name2pid(ptr + 14, &pid)) { | ||
846 | if (!cfg.shell && !arg_shell_none) | ||
847 | cfg.shell = guess_shell(); | ||
848 | |||
849 | // find first non-option arg | ||
850 | int i; | ||
851 | for (i = 1; i < cfg.original_argc && strncmp(cfg.original_argv[i], "--", 2) != 0; i++); | ||
852 | |||
853 | join(pid, cfg.original_argc,cfg.original_argv, i + 1); | ||
854 | exit(0); | ||
855 | } | ||
856 | |||
857 | // set sandbox name and start normally | ||
858 | cfg.name = ptr + 14; | ||
859 | if (strlen(cfg.name) == 0) { | ||
860 | fprintf(stderr, "Error: invalid sandbox name\n"); | ||
861 | exit(1); | ||
862 | } | ||
863 | return 0; | ||
864 | } | ||
865 | |||
572 | // rest of filesystem | 866 | // rest of filesystem |
573 | if (strncmp(ptr, "blacklist ", 10) == 0) | 867 | if (strncmp(ptr, "blacklist ", 10) == 0) |
574 | ptr += 10; | 868 | ptr += 10; |
@@ -577,11 +871,23 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
577 | else if (strncmp(ptr, "noblacklist ", 12) == 0) | 871 | else if (strncmp(ptr, "noblacklist ", 12) == 0) |
578 | ptr += 12; | 872 | ptr += 12; |
579 | else if (strncmp(ptr, "whitelist ", 10) == 0) { | 873 | else if (strncmp(ptr, "whitelist ", 10) == 0) { |
580 | arg_whitelist = 1; | 874 | #ifdef HAVE_WHITELIST |
581 | ptr += 10; | 875 | if (checkcfg(CFG_WHITELIST)) { |
876 | arg_whitelist = 1; | ||
877 | ptr += 10; | ||
878 | } | ||
879 | else | ||
880 | return 0; | ||
881 | #else | ||
882 | return 0; | ||
883 | #endif | ||
582 | } | 884 | } |
583 | else if (strncmp(ptr, "read-only ", 10) == 0) | 885 | else if (strncmp(ptr, "read-only ", 10) == 0) |
584 | ptr += 10; | 886 | ptr += 10; |
887 | else if (strncmp(ptr, "read-write ", 11) == 0) | ||
888 | ptr += 11; | ||
889 | else if (strncmp(ptr, "noexec ", 7) == 0) | ||
890 | ptr += 7; | ||
585 | else if (strncmp(ptr, "tmpfs ", 6) == 0) { | 891 | else if (strncmp(ptr, "tmpfs ", 6) == 0) { |
586 | if (getuid() != 0) { | 892 | if (getuid() != 0) { |
587 | fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n"); | 893 | fprintf(stderr, "Error: tmpfs available only when running the sandbox as root\n"); |
@@ -651,6 +957,16 @@ void profile_read(const char *fname) { | |||
651 | exit(1); | 957 | exit(1); |
652 | } | 958 | } |
653 | 959 | ||
960 | // allow debuggers | ||
961 | if (arg_allow_debuggers) { | ||
962 | char *tmp = strrchr(fname, '/'); | ||
963 | if (tmp && *(tmp + 1) != '\0') { | ||
964 | tmp++; | ||
965 | if (strcmp(tmp, "disable-devel.inc") == 0) | ||
966 | return; | ||
967 | } | ||
968 | } | ||
969 | |||
654 | // open profile file: | 970 | // open profile file: |
655 | FILE *fp = fopen(fname, "r"); | 971 | FILE *fp = fopen(fname, "r"); |
656 | if (fp == NULL) { | 972 | if (fp == NULL) { |
@@ -658,8 +974,7 @@ void profile_read(const char *fname) { | |||
658 | exit(1); | 974 | exit(1); |
659 | } | 975 | } |
660 | 976 | ||
661 | if (!arg_quiet) | 977 | int msg_printed = 0; |
662 | fprintf(stderr, "Reading profile %s\n", fname); | ||
663 | 978 | ||
664 | // read the file line by line | 979 | // read the file line by line |
665 | char buf[MAX_READ + 1]; | 980 | char buf[MAX_READ + 1]; |
@@ -677,6 +992,17 @@ void profile_read(const char *fname) { | |||
677 | continue; | 992 | continue; |
678 | } | 993 | } |
679 | 994 | ||
995 | // process quiet | ||
996 | if (strcmp(ptr, "quiet") == 0) { | ||
997 | arg_quiet = 1; | ||
998 | continue; | ||
999 | } | ||
1000 | if (!msg_printed) { | ||
1001 | if (!arg_quiet) | ||
1002 | fprintf(stderr, "Reading profile %s\n", fname); | ||
1003 | msg_printed = 1; | ||
1004 | } | ||
1005 | |||
680 | // process include | 1006 | // process include |
681 | if (strncmp(ptr, "include ", 8) == 0) { | 1007 | if (strncmp(ptr, "include ", 8) == 0) { |
682 | include_level++; | 1008 | include_level++; |