diff options
Diffstat (limited to 'src/firejail/sandbox.c')
-rw-r--r-- | src/firejail/sandbox.c | 297 |
1 files changed, 154 insertions, 143 deletions
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 8021ce9a3..3942e4da6 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -122,7 +122,7 @@ static void sandbox_if_up(Bridge *br) { | |||
122 | assert(br); | 122 | assert(br); |
123 | if (!br->configured) | 123 | if (!br->configured) |
124 | return; | 124 | return; |
125 | 125 | ||
126 | char *dev = br->devsandbox; | 126 | char *dev = br->devsandbox; |
127 | net_if_up(dev); | 127 | net_if_up(dev); |
128 | 128 | ||
@@ -137,8 +137,7 @@ static void sandbox_if_up(Bridge *br) { | |||
137 | assert(br->ipsandbox); | 137 | assert(br->ipsandbox); |
138 | if (arg_debug) | 138 | if (arg_debug) |
139 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); | 139 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); |
140 | net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); | 140 | net_config_interface(dev, br->ipsandbox, br->mask, br->mtu); |
141 | net_if_up(dev); | ||
142 | } | 141 | } |
143 | else if (br->arg_ip_none == 0 && br->macvlan == 1) { | 142 | else if (br->arg_ip_none == 0 && br->macvlan == 1) { |
144 | // reassign the macvlan address | 143 | // reassign the macvlan address |
@@ -160,8 +159,7 @@ static void sandbox_if_up(Bridge *br) { | |||
160 | 159 | ||
161 | if (arg_debug) | 160 | if (arg_debug) |
162 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); | 161 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(br->ipsandbox), dev); |
163 | net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); | 162 | net_config_interface(dev, br->ipsandbox, br->mask, br->mtu); |
164 | net_if_up(dev); | ||
165 | } | 163 | } |
166 | 164 | ||
167 | if (br->ip6sandbox) | 165 | if (br->ip6sandbox) |
@@ -256,32 +254,6 @@ static int monitor_application(pid_t app_pid) { | |||
256 | 254 | ||
257 | // return the latest exit status. | 255 | // return the latest exit status. |
258 | return status; | 256 | return status; |
259 | |||
260 | #if 0 | ||
261 | // todo: find a way to shut down interfaces before closing the namespace | ||
262 | // the problem is we don't have enough privileges to shutdown interfaces in this moment | ||
263 | // shut down bridge/macvlan interfaces | ||
264 | if (any_bridge_configured()) { | ||
265 | |||
266 | if (cfg.bridge0.configured) { | ||
267 | printf("Shutting down %s\n", cfg.bridge0.devsandbox); | ||
268 | net_if_down( cfg.bridge0.devsandbox); | ||
269 | } | ||
270 | if (cfg.bridge1.configured) { | ||
271 | printf("Shutting down %s\n", cfg.bridge1.devsandbox); | ||
272 | net_if_down( cfg.bridge1.devsandbox); | ||
273 | } | ||
274 | if (cfg.bridge2.configured) { | ||
275 | printf("Shutting down %s\n", cfg.bridge2.devsandbox); | ||
276 | net_if_down( cfg.bridge2.devsandbox); | ||
277 | } | ||
278 | if (cfg.bridge3.configured) { | ||
279 | printf("Shutting down %s\n", cfg.bridge3.devsandbox); | ||
280 | net_if_down( cfg.bridge3.devsandbox); | ||
281 | } | ||
282 | usleep(20000); // 20 ms sleep | ||
283 | } | ||
284 | #endif | ||
285 | } | 257 | } |
286 | 258 | ||
287 | void start_audit(void) { | 259 | void start_audit(void) { |
@@ -442,7 +414,8 @@ int sandbox(void* sandbox_arg) { | |||
442 | if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { | 414 | if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { |
443 | chk_chroot(); | 415 | chk_chroot(); |
444 | } | 416 | } |
445 | 417 | // ... and mount a tmpfs on top of /run/firejail/mnt directory | |
418 | preproc_mount_mnt_dir(); | ||
446 | 419 | ||
447 | //**************************** | 420 | //**************************** |
448 | // log sandbox data | 421 | // log sandbox data |
@@ -459,7 +432,7 @@ int sandbox(void* sandbox_arg) { | |||
459 | fs_logger("install mount namespace"); | 432 | fs_logger("install mount namespace"); |
460 | 433 | ||
461 | //**************************** | 434 | //**************************** |
462 | // netfilter etc. | 435 | // netfilter |
463 | //**************************** | 436 | //**************************** |
464 | if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter | 437 | if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter |
465 | netfilter(arg_netfilter_file); | 438 | netfilter(arg_netfilter_file); |
@@ -468,6 +441,105 @@ int sandbox(void* sandbox_arg) { | |||
468 | netfilter6(arg_netfilter6_file); | 441 | netfilter6(arg_netfilter6_file); |
469 | } | 442 | } |
470 | 443 | ||
444 | //**************************** | ||
445 | // networking | ||
446 | //**************************** | ||
447 | int gw_cfg_failed = 0; // default gw configuration flag | ||
448 | if (arg_nonetwork) { | ||
449 | net_if_up("lo"); | ||
450 | if (arg_debug) | ||
451 | printf("Network namespace enabled, only loopback interface available\n"); | ||
452 | } | ||
453 | else if (any_bridge_configured() || any_interface_configured()) { | ||
454 | // configure lo and eth0...eth3 | ||
455 | net_if_up("lo"); | ||
456 | |||
457 | if (mac_not_zero(cfg.bridge0.macsandbox)) | ||
458 | net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); | ||
459 | sandbox_if_up(&cfg.bridge0); | ||
460 | |||
461 | if (mac_not_zero(cfg.bridge1.macsandbox)) | ||
462 | net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); | ||
463 | sandbox_if_up(&cfg.bridge1); | ||
464 | |||
465 | if (mac_not_zero(cfg.bridge2.macsandbox)) | ||
466 | net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); | ||
467 | sandbox_if_up(&cfg.bridge2); | ||
468 | |||
469 | if (mac_not_zero(cfg.bridge3.macsandbox)) | ||
470 | net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); | ||
471 | sandbox_if_up(&cfg.bridge3); | ||
472 | |||
473 | |||
474 | // todo: this code seems to be dead!!! | ||
475 | // enable interfaces | ||
476 | if (cfg.interface0.configured && cfg.interface0.ip) { | ||
477 | assert(0); | ||
478 | if (arg_debug) | ||
479 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev); | ||
480 | net_config_interface(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu); | ||
481 | } | ||
482 | if (cfg.interface1.configured && cfg.interface1.ip) { | ||
483 | assert(0); | ||
484 | if (arg_debug) | ||
485 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev); | ||
486 | net_config_interface(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu); | ||
487 | } | ||
488 | if (cfg.interface2.configured && cfg.interface2.ip) { | ||
489 | assert(0); | ||
490 | if (arg_debug) | ||
491 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev); | ||
492 | net_config_interface(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu); | ||
493 | } | ||
494 | if (cfg.interface3.configured && cfg.interface3.ip) { | ||
495 | assert(0); | ||
496 | if (arg_debug) | ||
497 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev); | ||
498 | net_config_interface(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu); | ||
499 | } | ||
500 | |||
501 | // add a default route | ||
502 | if (cfg.defaultgw) { | ||
503 | // set the default route | ||
504 | if (net_add_route(0, 0, cfg.defaultgw)) { | ||
505 | fprintf(stderr, "Warning: cannot configure default route\n"); | ||
506 | gw_cfg_failed = 1; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | if (arg_debug) | ||
511 | printf("Network namespace enabled\n"); | ||
512 | } | ||
513 | |||
514 | |||
515 | // print network configuration | ||
516 | if (!arg_quiet) { | ||
517 | if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) { | ||
518 | printf("\n"); | ||
519 | if (any_bridge_configured() || any_interface_configured()) { | ||
520 | // net_ifprint(); | ||
521 | if (arg_scan) | ||
522 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, PATH_FNET, "printif", "scan"); | ||
523 | else | ||
524 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, PATH_FNET, "printif", "scan"); | ||
525 | |||
526 | } | ||
527 | if (cfg.defaultgw != 0) { | ||
528 | if (gw_cfg_failed) | ||
529 | printf("Default gateway configuration failed\n"); | ||
530 | else | ||
531 | printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw)); | ||
532 | } | ||
533 | if (cfg.dns1 != 0) | ||
534 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); | ||
535 | if (cfg.dns2 != 0) | ||
536 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); | ||
537 | if (cfg.dns3 != 0) | ||
538 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); | ||
539 | printf("\n"); | ||
540 | } | ||
541 | } | ||
542 | |||
471 | // load IBUS env variables | 543 | // load IBUS env variables |
472 | if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { | 544 | if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { |
473 | // do nothing - there are problems with ibus version 1.5.11 | 545 | // do nothing - there are problems with ibus version 1.5.11 |
@@ -475,9 +547,27 @@ int sandbox(void* sandbox_arg) { | |||
475 | else | 547 | else |
476 | env_ibus_load(); | 548 | env_ibus_load(); |
477 | 549 | ||
478 | // grab a copy of cp command | 550 | //**************************** |
479 | fs_build_cp_command(); | 551 | // fs pre-processing: |
480 | 552 | // - copy some commands under /run | |
553 | // - build seccomp filters | ||
554 | // - create an empty /etc/ld.so.preload | ||
555 | //**************************** | ||
556 | preproc_build_cp_command(); | ||
557 | |||
558 | #ifdef HAVE_SECCOMP | ||
559 | if (cfg.protocol) { | ||
560 | if (arg_debug) | ||
561 | printf("Build protocol filter: %s\n", cfg.protocol); | ||
562 | |||
563 | // build the seccomp filter as a regular user | ||
564 | int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5, | ||
565 | PATH_FSECCOMP, "protocol", "build", cfg.protocol, RUN_SECCOMP_PROTOCOL); | ||
566 | if (rv) | ||
567 | exit(rv); | ||
568 | } | ||
569 | #endif | ||
570 | |||
481 | // trace pre-install | 571 | // trace pre-install |
482 | if (arg_trace || arg_tracelog || mask_x11_abstract_socket) | 572 | if (arg_trace || arg_tracelog || mask_x11_abstract_socket) |
483 | fs_trace_preload(); | 573 | fs_trace_preload(); |
@@ -488,6 +578,13 @@ int sandbox(void* sandbox_arg) { | |||
488 | #ifdef HAVE_SECCOMP | 578 | #ifdef HAVE_SECCOMP |
489 | int enforce_seccomp = 0; | 579 | int enforce_seccomp = 0; |
490 | #endif | 580 | #endif |
581 | if (arg_appimage) { | ||
582 | enforce_filters(); | ||
583 | #ifdef HAVE_SECCOMP | ||
584 | enforce_seccomp = 1; | ||
585 | #endif | ||
586 | } | ||
587 | |||
491 | #ifdef HAVE_CHROOT | 588 | #ifdef HAVE_CHROOT |
492 | if (cfg.chrootdir) { | 589 | if (cfg.chrootdir) { |
493 | fs_chroot(cfg.chrootdir); | 590 | fs_chroot(cfg.chrootdir); |
@@ -610,7 +707,6 @@ int sandbox(void* sandbox_arg) { | |||
610 | EUID_USER(); | 707 | EUID_USER(); |
611 | profile_add("whitelist /tmp/.X11-unix"); | 708 | profile_add("whitelist /tmp/.X11-unix"); |
612 | EUID_ROOT(); | 709 | EUID_ROOT(); |
613 | // fs_private_tmp(); | ||
614 | } | 710 | } |
615 | } | 711 | } |
616 | 712 | ||
@@ -657,102 +753,17 @@ int sandbox(void* sandbox_arg) { | |||
657 | fs_dev_disable_3d(); | 753 | fs_dev_disable_3d(); |
658 | 754 | ||
659 | //**************************** | 755 | //**************************** |
660 | // networking | 756 | // set dns |
661 | //**************************** | 757 | //**************************** |
662 | int gw_cfg_failed = 0; // default gw configuration flag | ||
663 | if (arg_nonetwork) { | ||
664 | net_if_up("lo"); | ||
665 | if (arg_debug) | ||
666 | printf("Network namespace enabled, only loopback interface available\n"); | ||
667 | } | ||
668 | else if (any_bridge_configured() || any_interface_configured()) { | ||
669 | // configure lo and eth0...eth3 | ||
670 | net_if_up("lo"); | ||
671 | |||
672 | if (mac_not_zero(cfg.bridge0.macsandbox)) | ||
673 | net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox); | ||
674 | sandbox_if_up(&cfg.bridge0); | ||
675 | |||
676 | if (mac_not_zero(cfg.bridge1.macsandbox)) | ||
677 | net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox); | ||
678 | sandbox_if_up(&cfg.bridge1); | ||
679 | |||
680 | if (mac_not_zero(cfg.bridge2.macsandbox)) | ||
681 | net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox); | ||
682 | sandbox_if_up(&cfg.bridge2); | ||
683 | |||
684 | if (mac_not_zero(cfg.bridge3.macsandbox)) | ||
685 | net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox); | ||
686 | sandbox_if_up(&cfg.bridge3); | ||
687 | |||
688 | // enable interfaces | ||
689 | if (cfg.interface0.configured && cfg.interface0.ip) { | ||
690 | if (arg_debug) | ||
691 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev); | ||
692 | net_if_ip(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu); | ||
693 | net_if_up(cfg.interface0.dev); | ||
694 | } | ||
695 | if (cfg.interface1.configured && cfg.interface1.ip) { | ||
696 | if (arg_debug) | ||
697 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev); | ||
698 | net_if_ip(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu); | ||
699 | net_if_up(cfg.interface1.dev); | ||
700 | } | ||
701 | if (cfg.interface2.configured && cfg.interface2.ip) { | ||
702 | if (arg_debug) | ||
703 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev); | ||
704 | net_if_ip(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu); | ||
705 | net_if_up(cfg.interface2.dev); | ||
706 | } | ||
707 | if (cfg.interface3.configured && cfg.interface3.ip) { | ||
708 | if (arg_debug) | ||
709 | printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev); | ||
710 | net_if_ip(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu); | ||
711 | net_if_up(cfg.interface3.dev); | ||
712 | } | ||
713 | |||
714 | // add a default route | ||
715 | if (cfg.defaultgw) { | ||
716 | // set the default route | ||
717 | if (net_add_route(0, 0, cfg.defaultgw)) { | ||
718 | fprintf(stderr, "Warning: cannot configure default route\n"); | ||
719 | gw_cfg_failed = 1; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | if (arg_debug) | ||
724 | printf("Network namespace enabled\n"); | ||
725 | } | ||
726 | |||
727 | // if any dns server is configured, it is time to set it now | ||
728 | fs_resolvconf(); | 758 | fs_resolvconf(); |
759 | |||
760 | //**************************** | ||
761 | // fs post-processing | ||
762 | //**************************** | ||
763 | preproc_delete_cp_command(); | ||
729 | fs_logger_print(); | 764 | fs_logger_print(); |
730 | fs_logger_change_owner(); | 765 | fs_logger_change_owner(); |
731 | 766 | ||
732 | // print network configuration | ||
733 | if (!arg_quiet) { | ||
734 | if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) { | ||
735 | printf("\n"); | ||
736 | if (any_bridge_configured() || any_interface_configured()) | ||
737 | net_ifprint(); | ||
738 | if (cfg.defaultgw != 0) { | ||
739 | if (gw_cfg_failed) | ||
740 | printf("Default gateway configuration failed\n"); | ||
741 | else | ||
742 | printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw)); | ||
743 | } | ||
744 | if (cfg.dns1 != 0) | ||
745 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1)); | ||
746 | if (cfg.dns2 != 0) | ||
747 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2)); | ||
748 | if (cfg.dns3 != 0) | ||
749 | printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3)); | ||
750 | printf("\n"); | ||
751 | } | ||
752 | } | ||
753 | |||
754 | fs_delete_cp_command(); | ||
755 | |||
756 | //**************************** | 767 | //**************************** |
757 | // set application environment | 768 | // set application environment |
758 | //**************************** | 769 | //**************************** |
@@ -808,12 +819,24 @@ int sandbox(void* sandbox_arg) { | |||
808 | // set rlimits | 819 | // set rlimits |
809 | set_rlimits(); | 820 | set_rlimits(); |
810 | 821 | ||
811 | // set seccomp | 822 | // set cpu affinity |
823 | if (cfg.cpus) { | ||
824 | save_cpu(); // save cpu affinity mask to CPU_CFG file | ||
825 | set_cpu_affinity(); | ||
826 | } | ||
827 | |||
828 | // save cgroup in CGROUP_CFG file | ||
829 | if (cfg.cgroup) | ||
830 | save_cgroup(); | ||
831 | |||
832 | // set seccomp //todo: push it down after drop_privs and/or configuring noroot | ||
812 | #ifdef HAVE_SECCOMP | 833 | #ifdef HAVE_SECCOMP |
813 | // install protocol filter | 834 | // install protocol filter |
814 | if (cfg.protocol) { | 835 | if (cfg.protocol) { |
815 | protocol_filter(); // install filter | 836 | if (arg_debug) |
816 | protocol_filter_save(); // save filter in PROTOCOL_CFG | 837 | printf("Install protocol filter: %s\n", cfg.protocol); |
838 | seccomp_load(RUN_SECCOMP_PROTOCOL); // install filter | ||
839 | protocol_filter_save(); // save filter in RUN_PROTOCOL_CFG | ||
817 | } | 840 | } |
818 | 841 | ||
819 | // if a keep list is available, disregard the drop list | 842 | // if a keep list is available, disregard the drop list |
@@ -827,16 +850,6 @@ int sandbox(void* sandbox_arg) { | |||
827 | } | 850 | } |
828 | #endif | 851 | #endif |
829 | 852 | ||
830 | // set cpu affinity | ||
831 | if (cfg.cpus) { | ||
832 | save_cpu(); // save cpu affinity mask to CPU_CFG file | ||
833 | set_cpu_affinity(); | ||
834 | } | ||
835 | |||
836 | // save cgroup in CGROUP_CFG file | ||
837 | if (cfg.cgroup) | ||
838 | save_cgroup(); | ||
839 | |||
840 | //**************************************** | 853 | //**************************************** |
841 | // drop privileges or create a new user namespace | 854 | // drop privileges or create a new user namespace |
842 | //**************************************** | 855 | //**************************************** |
@@ -909,8 +922,6 @@ int sandbox(void* sandbox_arg) { | |||
909 | int status = monitor_application(app_pid); // monitor application | 922 | int status = monitor_application(app_pid); // monitor application |
910 | flush_stdin(); | 923 | flush_stdin(); |
911 | 924 | ||
912 | |||
913 | |||
914 | if (WIFEXITED(status)) { | 925 | if (WIFEXITED(status)) { |
915 | // if we had a proper exit, return that exit status | 926 | // if we had a proper exit, return that exit status |
916 | return WEXITSTATUS(status); | 927 | return WEXITSTATUS(status); |