aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/sandbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/sandbox.c')
-rw-r--r--src/firejail/sandbox.c618
1 files changed, 392 insertions, 226 deletions
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 3f3564295..109daf552 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -28,12 +28,23 @@
28#include <sys/types.h> 28#include <sys/types.h>
29#include <dirent.h> 29#include <dirent.h>
30#include <errno.h> 30#include <errno.h>
31#include <fcntl.h>
31 32
32#include <sched.h> 33#include <sched.h>
33#ifndef CLONE_NEWUSER 34#ifndef CLONE_NEWUSER
34#define CLONE_NEWUSER 0x10000000 35#define CLONE_NEWUSER 0x10000000
35#endif 36#endif
36 37
38#include <sys/prctl.h>
39#ifndef PR_SET_NO_NEW_PRIVS
40# define PR_SET_NO_NEW_PRIVS 38
41#endif
42
43#ifdef HAVE_APPARMOR
44#include <sys/apparmor.h>
45#endif
46
47
37static int monitored_pid = 0; 48static int monitored_pid = 0;
38static void sandbox_handler(int sig){ 49static void sandbox_handler(int sig){
39 if (!arg_quiet) { 50 if (!arg_quiet) {
@@ -70,8 +81,11 @@ static void sandbox_handler(int sig){
70 81
71 } 82 }
72 83
84
73 // broadcast a SIGKILL 85 // broadcast a SIGKILL
74 kill(-1, SIGKILL); 86 kill(-1, SIGKILL);
87 flush_stdin();
88
75 exit(sig); 89 exit(sig);
76} 90}
77 91
@@ -94,9 +108,8 @@ void save_nogroups(void) {
94 FILE *fp = fopen(RUN_GROUPS_CFG, "w"); 108 FILE *fp = fopen(RUN_GROUPS_CFG, "w");
95 if (fp) { 109 if (fp) {
96 fprintf(fp, "\n"); 110 fprintf(fp, "\n");
111 SET_PERMS_STREAM(fp, 0, 0, 0644); // assume mode 0644
97 fclose(fp); 112 fclose(fp);
98 if (chown(RUN_GROUPS_CFG, 0, 0) < 0)
99 errExit("chown");
100 } 113 }
101 else { 114 else {
102 fprintf(stderr, "Error: cannot save nogroups state\n"); 115 fprintf(stderr, "Error: cannot save nogroups state\n");
@@ -109,7 +122,7 @@ static void sandbox_if_up(Bridge *br) {
109 assert(br); 122 assert(br);
110 if (!br->configured) 123 if (!br->configured)
111 return; 124 return;
112 125
113 char *dev = br->devsandbox; 126 char *dev = br->devsandbox;
114 net_if_up(dev); 127 net_if_up(dev);
115 128
@@ -124,8 +137,7 @@ static void sandbox_if_up(Bridge *br) {
124 assert(br->ipsandbox); 137 assert(br->ipsandbox);
125 if (arg_debug) 138 if (arg_debug)
126 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);
127 net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); 140 net_config_interface(dev, br->ipsandbox, br->mask, br->mtu);
128 net_if_up(dev);
129 } 141 }
130 else if (br->arg_ip_none == 0 && br->macvlan == 1) { 142 else if (br->arg_ip_none == 0 && br->macvlan == 1) {
131 // reassign the macvlan address 143 // reassign the macvlan address
@@ -147,8 +159,7 @@ static void sandbox_if_up(Bridge *br) {
147 159
148 if (arg_debug) 160 if (arg_debug)
149 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);
150 net_if_ip(dev, br->ipsandbox, br->mask, br->mtu); 162 net_config_interface(dev, br->ipsandbox, br->mask, br->mtu);
151 net_if_up(dev);
152 } 163 }
153 164
154 if (br->ip6sandbox) 165 if (br->ip6sandbox)
@@ -198,6 +209,12 @@ static int monitor_application(pid_t app_pid) {
198 if (arg_debug) 209 if (arg_debug)
199 printf("Sandbox monitor: waitpid %u retval %d status %d\n", monitored_pid, rv, status); 210 printf("Sandbox monitor: waitpid %u retval %d status %d\n", monitored_pid, rv, status);
200 211
212 // if /proc is not remounted, we cannot check /proc directory,
213 // for now we just get out of here
214 // todo: find another way of checking child processes!
215 if (!checkcfg(CFG_REMOUNT_PROC_SYS))
216 break;
217
201 DIR *dir; 218 DIR *dir;
202 if (!(dir = opendir("/proc"))) { 219 if (!(dir = opendir("/proc"))) {
203 // sleep 2 seconds and try again 220 // sleep 2 seconds and try again
@@ -237,40 +254,46 @@ static int monitor_application(pid_t app_pid) {
237 254
238 // return the latest exit status. 255 // return the latest exit status.
239 return status; 256 return status;
257}
240 258
241#if 0 259void start_audit(void) {
242// todo: find a way to shut down interfaces before closing the namespace 260 char *audit_prog;
243// the problem is we don't have enough privileges to shutdown interfaces in this moment 261 if (asprintf(&audit_prog, "%s/firejail/faudit", LIBDIR) == -1)
244 // shut down bridge/macvlan interfaces 262 errExit("asprintf");
245 if (any_bridge_configured()) { 263 assert(getenv("LD_PRELOAD") == NULL);
246 264 execl(audit_prog, audit_prog, NULL);
247 if (cfg.bridge0.configured) { 265 perror("execl");
248 printf("Shutting down %s\n", cfg.bridge0.devsandbox); 266 exit(1);
249 net_if_down( cfg.bridge0.devsandbox);
250 }
251 if (cfg.bridge1.configured) {
252 printf("Shutting down %s\n", cfg.bridge1.devsandbox);
253 net_if_down( cfg.bridge1.devsandbox);
254 }
255 if (cfg.bridge2.configured) {
256 printf("Shutting down %s\n", cfg.bridge2.devsandbox);
257 net_if_down( cfg.bridge2.devsandbox);
258 }
259 if (cfg.bridge3.configured) {
260 printf("Shutting down %s\n", cfg.bridge3.devsandbox);
261 net_if_down( cfg.bridge3.devsandbox);
262 }
263 usleep(20000); // 20 ms sleep
264 }
265#endif
266} 267}
267 268
269void start_application(void) {
270//if (setsid() == -1)
271//errExit("setsid");
268 272
269static void start_application(void) { 273 // set environment
274 env_defaults();
275 env_apply();
276 if (arg_debug) {
277 printf("starting application\n");
278 printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD"));
279 }
280
281 //****************************************
282 // audit
283 //****************************************
284 if (arg_audit) {
285 assert(arg_audit_prog);
286 struct stat s;
287 if (stat(arg_audit_prog, &s) != 0) {
288 fprintf(stderr, "Error: cannot find the audit program\n");
289 exit(1);
290 }
291 execl(arg_audit_prog, arg_audit_prog, NULL);
292 }
270 //**************************************** 293 //****************************************
271 // start the program without using a shell 294 // start the program without using a shell
272 //**************************************** 295 //****************************************
273 if (arg_shell_none) { 296 else if (arg_shell_none) {
274 if (arg_debug) { 297 if (arg_debug) {
275 int i; 298 int i;
276 for (i = cfg.original_program_index; i < cfg.original_argc; i++) { 299 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
@@ -289,35 +312,33 @@ static void start_application(void) {
289 printf("Child process initialized\n"); 312 printf("Child process initialized\n");
290 313
291 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); 314 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
315 exit(1);
292 } 316 }
293 //**************************************** 317 //****************************************
294 // start the program using a shell 318 // start the program using a shell
295 //**************************************** 319 //****************************************
296 else { 320 else {
297 // choose the shell requested by the user, or use bash as default 321 assert(cfg.shell);
298 char *sh; 322 assert(cfg.command_line);
299 if (cfg.shell) 323
300 sh = cfg.shell;
301 else if (arg_zsh)
302 sh = "/usr/bin/zsh";
303 else if (arg_csh)
304 sh = "/bin/csh";
305 else
306 sh = "/bin/bash";
307
308 char *arg[5]; 324 char *arg[5];
309 int index = 0; 325 int index = 0;
310 arg[index++] = sh; 326 arg[index++] = cfg.shell;
311 arg[index++] = "-c"; 327 if (login_shell) {
312 assert(cfg.command_line); 328 arg[index++] = "-l";
313 if (arg_debug) 329 if (arg_debug)
314 printf("Starting %s\n", cfg.command_line); 330 printf("Starting %s login shell\n", cfg.shell);
315 if (arg_doubledash) 331 } else {
316 arg[index++] = "--"; 332 arg[index++] = "-c";
317 arg[index++] = cfg.command_line; 333 if (arg_debug)
334 printf("Running %s command through %s\n", cfg.command_line, cfg.shell);
335 if (arg_doubledash)
336 arg[index++] = "--";
337 arg[index++] = cfg.command_line;
338 }
318 arg[index] = NULL; 339 arg[index] = NULL;
319 assert(index < 5); 340 assert(index < 5);
320 341
321 if (arg_debug) { 342 if (arg_debug) {
322 char *msg; 343 char *msg;
323 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) 344 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
@@ -325,7 +346,7 @@ static void start_application(void) {
325 logmsg(msg); 346 logmsg(msg);
326 free(msg); 347 free(msg);
327 } 348 }
328 349
329 if (arg_debug) { 350 if (arg_debug) {
330 int i; 351 int i;
331 for (i = 0; i < 5; i++) { 352 for (i = 0; i < 5; i++) {
@@ -334,17 +355,40 @@ static void start_application(void) {
334 printf("execvp argument %d: %s\n", i, arg[i]); 355 printf("execvp argument %d: %s\n", i, arg[i]);
335 } 356 }
336 } 357 }
337 358
338 if (!arg_command && !arg_quiet) 359 if (!arg_command && !arg_quiet)
339 printf("Child process initialized\n"); 360 printf("Child process initialized\n");
340 execvp(sh, arg); 361 execvp(arg[0], arg);
341 } 362 }
342 363
343 perror("execvp"); 364 perror("execvp");
344 exit(1); // it should never get here!!! 365 exit(1); // it should never get here!!!
345} 366}
346 367
347 368static void enforce_filters(void) {
369 // force default seccomp inside the chroot, no keep or drop list
370 // the list build on top of the default drop list is kept intact
371 arg_seccomp = 1;
372 if (cfg.seccomp_list_drop) {
373 free(cfg.seccomp_list_drop);
374 cfg.seccomp_list_drop = NULL;
375 }
376 if (cfg.seccomp_list_keep) {
377 free(cfg.seccomp_list_keep);
378 cfg.seccomp_list_keep = NULL;
379 }
380
381 // disable all capabilities
382 if (arg_caps_default_filter || arg_caps_list)
383 fprintf(stderr, "Warning: all capabilities disabled for a regular user in chroot\n");
384 arg_caps_drop_all = 1;
385
386 // drop all supplementary groups; /etc/group file inside chroot
387 // is controlled by a regular usr
388 arg_nogroups = 1;
389 if (!arg_quiet)
390 printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
391}
348 392
349int sandbox(void* sandbox_arg) { 393int sandbox(void* sandbox_arg) {
350 // Get rid of unused parameter warning 394 // Get rid of unused parameter warning
@@ -364,6 +408,7 @@ int sandbox(void* sandbox_arg) {
364 if (arg_debug && child_pid == 1) 408 if (arg_debug && child_pid == 1)
365 printf("PID namespace installed\n"); 409 printf("PID namespace installed\n");
366 410
411
367 //**************************** 412 //****************************
368 // set hostname 413 // set hostname
369 //**************************** 414 //****************************
@@ -379,7 +424,8 @@ int sandbox(void* sandbox_arg) {
379 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { 424 if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
380 chk_chroot(); 425 chk_chroot();
381 } 426 }
382 427 // ... and mount a tmpfs on top of /run/firejail/mnt directory
428 preproc_mount_mnt_dir();
383 429
384 //**************************** 430 //****************************
385 // log sandbox data 431 // log sandbox data
@@ -396,7 +442,7 @@ int sandbox(void* sandbox_arg) {
396 fs_logger("install mount namespace"); 442 fs_logger("install mount namespace");
397 443
398 //**************************** 444 //****************************
399 // netfilter etc. 445 // netfilter
400 //**************************** 446 //****************************
401 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter 447 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
402 netfilter(arg_netfilter_file); 448 netfilter(arg_netfilter_file);
@@ -405,6 +451,101 @@ int sandbox(void* sandbox_arg) {
405 netfilter6(arg_netfilter6_file); 451 netfilter6(arg_netfilter6_file);
406 } 452 }
407 453
454 //****************************
455 // networking
456 //****************************
457 int gw_cfg_failed = 0; // default gw configuration flag
458 if (arg_nonetwork) {
459 net_if_up("lo");
460 if (arg_debug)
461 printf("Network namespace enabled, only loopback interface available\n");
462 }
463 else if (any_bridge_configured() || any_interface_configured()) {
464 // configure lo and eth0...eth3
465 net_if_up("lo");
466
467 if (mac_not_zero(cfg.bridge0.macsandbox))
468 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
469 sandbox_if_up(&cfg.bridge0);
470
471 if (mac_not_zero(cfg.bridge1.macsandbox))
472 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
473 sandbox_if_up(&cfg.bridge1);
474
475 if (mac_not_zero(cfg.bridge2.macsandbox))
476 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
477 sandbox_if_up(&cfg.bridge2);
478
479 if (mac_not_zero(cfg.bridge3.macsandbox))
480 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
481 sandbox_if_up(&cfg.bridge3);
482
483
484 // moving an interface in a namespace using --interface will reset the interface configuration;
485 // we need to put the configuration back
486 if (cfg.interface0.configured && cfg.interface0.ip) {
487 if (arg_debug)
488 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev);
489 net_config_interface(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu);
490 }
491 if (cfg.interface1.configured && cfg.interface1.ip) {
492 if (arg_debug)
493 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev);
494 net_config_interface(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu);
495 }
496 if (cfg.interface2.configured && cfg.interface2.ip) {
497 if (arg_debug)
498 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev);
499 net_config_interface(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu);
500 }
501 if (cfg.interface3.configured && cfg.interface3.ip) {
502 if (arg_debug)
503 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev);
504 net_config_interface(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu);
505 }
506
507 // add a default route
508 if (cfg.defaultgw) {
509 // set the default route
510 if (net_add_route(0, 0, cfg.defaultgw)) {
511 fprintf(stderr, "Warning: cannot configure default route\n");
512 gw_cfg_failed = 1;
513 }
514 }
515
516 if (arg_debug)
517 printf("Network namespace enabled\n");
518 }
519
520
521 // print network configuration
522 if (!arg_quiet) {
523 if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) {
524 printf("\n");
525 if (any_bridge_configured() || any_interface_configured()) {
526// net_ifprint();
527 if (arg_scan)
528 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 3, PATH_FNET, "printif", "scan");
529 else
530 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, PATH_FNET, "printif", "scan");
531
532 }
533 if (cfg.defaultgw != 0) {
534 if (gw_cfg_failed)
535 printf("Default gateway configuration failed\n");
536 else
537 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
538 }
539 if (cfg.dns1 != 0)
540 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
541 if (cfg.dns2 != 0)
542 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
543 if (cfg.dns3 != 0)
544 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
545 printf("\n");
546 }
547 }
548
408 // load IBUS env variables 549 // load IBUS env variables
409 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) { 550 if (arg_nonetwork || any_bridge_configured() || any_interface_configured()) {
410 // do nothing - there are problems with ibus version 1.5.11 551 // do nothing - there are problems with ibus version 1.5.11
@@ -412,11 +553,29 @@ int sandbox(void* sandbox_arg) {
412 else 553 else
413 env_ibus_load(); 554 env_ibus_load();
414 555
415 // grab a copy of cp command 556 //****************************
416 fs_build_cp_command(); 557 // fs pre-processing:
417 558 // - copy some commands under /run
559 // - build seccomp filters
560 // - create an empty /etc/ld.so.preload
561 //****************************
562 preproc_build_cp_command();
563
564#ifdef HAVE_SECCOMP
565 if (cfg.protocol) {
566 if (arg_debug)
567 printf("Build protocol filter: %s\n", cfg.protocol);
568
569 // build the seccomp filter as a regular user
570 int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 5,
571 PATH_FSECCOMP, "protocol", "build", cfg.protocol, RUN_SECCOMP_PROTOCOL);
572 if (rv)
573 exit(rv);
574 }
575#endif
576
418 // trace pre-install 577 // trace pre-install
419 if (arg_trace || arg_tracelog) 578 if (arg_trace || arg_tracelog || mask_x11_abstract_socket)
420 fs_trace_preload(); 579 fs_trace_preload();
421 580
422 //**************************** 581 //****************************
@@ -425,39 +584,23 @@ int sandbox(void* sandbox_arg) {
425#ifdef HAVE_SECCOMP 584#ifdef HAVE_SECCOMP
426 int enforce_seccomp = 0; 585 int enforce_seccomp = 0;
427#endif 586#endif
587 if (arg_appimage) {
588 enforce_filters();
589#ifdef HAVE_SECCOMP
590 enforce_seccomp = 1;
591#endif
592 }
593
428#ifdef HAVE_CHROOT 594#ifdef HAVE_CHROOT
429 if (cfg.chrootdir) { 595 if (cfg.chrootdir) {
430 fs_chroot(cfg.chrootdir); 596 fs_chroot(cfg.chrootdir);
431 // redo cp command
432 fs_build_cp_command();
433 597
434 // force caps and seccomp if not started as root 598 // force caps and seccomp if not started as root
435 if (getuid() != 0) { 599 if (getuid() != 0) {
436 // force default seccomp inside the chroot, no keep or drop list 600 enforce_filters();
437 // the list build on top of the default drop list is kept intact
438 arg_seccomp = 1;
439#ifdef HAVE_SECCOMP 601#ifdef HAVE_SECCOMP
440 enforce_seccomp = 1; 602 enforce_seccomp = 1;
441#endif 603#endif
442 if (cfg.seccomp_list_drop) {
443 free(cfg.seccomp_list_drop);
444 cfg.seccomp_list_drop = NULL;
445 }
446 if (cfg.seccomp_list_keep) {
447 free(cfg.seccomp_list_keep);
448 cfg.seccomp_list_keep = NULL;
449 }
450
451 // disable all capabilities
452 if (arg_caps_default_filter || arg_caps_list)
453 fprintf(stderr, "Warning: all capabilities disabled for a regular user during chroot\n");
454 arg_caps_drop_all = 1;
455
456 // drop all supplementary groups; /etc/group file inside chroot
457 // is controlled by a regular usr
458 arg_nogroups = 1;
459 if (!arg_quiet)
460 printf("Dropping all Linux capabilities and enforcing default seccomp filter\n");
461 } 604 }
462 else 605 else
463 arg_seccomp = 1; 606 arg_seccomp = 1;
@@ -465,17 +608,28 @@ int sandbox(void* sandbox_arg) {
465 //**************************** 608 //****************************
466 // trace pre-install, this time inside chroot 609 // trace pre-install, this time inside chroot
467 //**************************** 610 //****************************
468 if (arg_trace || arg_tracelog) 611 if (arg_trace || arg_tracelog || mask_x11_abstract_socket)
469 fs_trace_preload(); 612 fs_trace_preload();
470 } 613 }
471 else 614 else
472#endif 615#endif
473 if (arg_overlay) 616#ifdef HAVE_OVERLAYFS
617 if (arg_overlay) {
474 fs_overlayfs(); 618 fs_overlayfs();
619 // force caps and seccomp if not started as root
620 if (getuid() != 0) {
621 enforce_filters();
622#ifdef HAVE_SECCOMP
623 enforce_seccomp = 1;
624#endif
625 }
626 else
627 arg_seccomp = 1;
628 }
475 else 629 else
630#endif
476 fs_basic_fs(); 631 fs_basic_fs();
477 632
478
479 //**************************** 633 //****************************
480 // set hostname in /etc/hostname 634 // set hostname in /etc/hostname
481 //**************************** 635 //****************************
@@ -487,145 +641,135 @@ int sandbox(void* sandbox_arg) {
487 // private mode 641 // private mode
488 //**************************** 642 //****************************
489 if (arg_private) { 643 if (arg_private) {
490 if (cfg.home_private) // --private= 644 if (cfg.home_private) { // --private=
491 fs_private_homedir(); 645 if (cfg.chrootdir)
646 fprintf(stderr, "Warning: private=directory feature is disabled in chroot\n");
647 else if (arg_overlay)
648 fprintf(stderr, "Warning: private=directory feature is disabled in overlay\n");
649 else
650 fs_private_homedir();
651 }
652 else if (cfg.home_private_keep) { // --private-home=
653 if (cfg.chrootdir)
654 fprintf(stderr, "Warning: private-home= feature is disabled in chroot\n");
655 else if (arg_overlay)
656 fprintf(stderr, "Warning: private-home= feature is disabled in overlay\n");
657 else
658 fs_private_home_list();
659 }
492 else // --private 660 else // --private
493 fs_private(); 661 fs_private();
494 } 662 }
495 663
496 if (arg_private_dev) 664 if (arg_private_dev) {
497 fs_private_dev(); 665 if (cfg.chrootdir)
666 fprintf(stderr, "Warning: private-dev feature is disabled in chroot\n");
667 else if (arg_overlay)
668 fprintf(stderr, "Warning: private-dev feature is disabled in overlay\n");
669 else
670 fs_private_dev();
671 }
672
498 if (arg_private_etc) { 673 if (arg_private_etc) {
499 fs_private_etc_list(); 674 if (cfg.chrootdir)
500 // create /etc/ld.so.preload file again 675 fprintf(stderr, "Warning: private-etc feature is disabled in chroot\n");
501 if (arg_trace || arg_tracelog) 676 else if (arg_overlay)
502 fs_trace_preload(); 677 fprintf(stderr, "Warning: private-etc feature is disabled in overlay\n");
678 else {
679 fs_private_etc_list();
680 // create /etc/ld.so.preload file again
681 if (arg_trace || arg_tracelog || mask_x11_abstract_socket)
682 fs_trace_preload();
683 }
684 }
685
686 if (arg_private_bin) {
687 if (cfg.chrootdir)
688 fprintf(stderr, "Warning: private-bin feature is disabled in chroot\n");
689 else if (arg_overlay)
690 fprintf(stderr, "Warning: private-bin feature is disabled in overlay\n");
691 else {
692 // for --x11=xorg we need to add xauth command
693 if (arg_x11_xorg) {
694 EUID_USER();
695 char *tmp;
696 if (asprintf(&tmp, "%s,xauth", cfg.bin_private_keep) == -1)
697 errExit("asprintf");
698 cfg.bin_private_keep = tmp;
699 fs_check_bin_list();
700 EUID_ROOT();
701 }
702 fs_private_bin_list();
703 }
704 }
705
706 if (arg_private_tmp) {
707 if (cfg.chrootdir)
708 fprintf(stderr, "Warning: private-tmp feature is disabled in chroot\n");
709 else if (arg_overlay)
710 fprintf(stderr, "Warning: private-tmp feature is disabled in overlay\n");
711 else {
712 // private-tmp is implemented as a whitelist
713 EUID_USER();
714 profile_add("whitelist /tmp/.X11-unix");
715 EUID_ROOT();
716 }
503 } 717 }
504 if (arg_private_bin) 718
505 fs_private_bin_list(); 719 //****************************
506 if (arg_private_tmp) 720 // update /proc, /sys, /dev, /boot directorymy
507 fs_private_tmp(); 721 //****************************
722 if (checkcfg(CFG_REMOUNT_PROC_SYS))
723 fs_proc_sys_dev_boot();
508 724
509 //**************************** 725 //****************************
510 // apply the profile file 726 // apply the profile file
511 //**************************** 727 //****************************
512 if (cfg.profile) { 728 // apply all whitelist commands ...
513 // apply all whitelist commands ... 729 if (cfg.chrootdir)
730 fprintf(stderr, "Warning: whitelist feature is disabled in chroot\n");
731 else if (arg_overlay)
732 fprintf(stderr, "Warning: whitelist feature is disabled in overlay\n");
733 else
514 fs_whitelist(); 734 fs_whitelist();
515 735
516 // ... followed by blacklist commands 736 // ... followed by blacklist commands
517 fs_blacklist(); 737 fs_blacklist(); // mkdir and mkfile are processed all over again
518 }
519 738
520 //**************************** 739 //****************************
521 // install trace 740 // install trace
522 //**************************** 741 //****************************
523 if (arg_trace || arg_tracelog) 742 if (arg_trace || arg_tracelog || mask_x11_abstract_socket)
524 fs_trace(); 743 fs_trace();
525 744
526 //**************************** 745 //****************************
527 // update /proc, /dev, /boot directorymy 746 // nosound/no3d and fix for pulseaudio 7.0
528 //****************************
529 fs_proc_sys_dev_boot();
530
531 //****************************
532 // --nosound and fix for pulseaudio 7.0
533 //**************************** 747 //****************************
534 if (arg_nosound) 748 if (arg_nosound) {
749 // disable pulseaudio
535 pulseaudio_disable(); 750 pulseaudio_disable();
751
752 // disable /dev/snd
753 fs_dev_disable_sound();
754 }
536 else 755 else
537 pulseaudio_init(); 756 pulseaudio_init();
538 757
758 if (arg_no3d)
759 fs_dev_disable_3d();
760
539 //**************************** 761 //****************************
540 // networking 762 // set dns
541 //**************************** 763 //****************************
542 if (arg_nonetwork) {
543 net_if_up("lo");
544 if (arg_debug)
545 printf("Network namespace enabled, only loopback interface available\n");
546 }
547 else if (any_bridge_configured() || any_interface_configured()) {
548 // configure lo and eth0...eth3
549 net_if_up("lo");
550
551 if (mac_not_zero(cfg.bridge0.macsandbox))
552 net_config_mac(cfg.bridge0.devsandbox, cfg.bridge0.macsandbox);
553 sandbox_if_up(&cfg.bridge0);
554
555 if (mac_not_zero(cfg.bridge1.macsandbox))
556 net_config_mac(cfg.bridge1.devsandbox, cfg.bridge1.macsandbox);
557 sandbox_if_up(&cfg.bridge1);
558
559 if (mac_not_zero(cfg.bridge2.macsandbox))
560 net_config_mac(cfg.bridge2.devsandbox, cfg.bridge2.macsandbox);
561 sandbox_if_up(&cfg.bridge2);
562
563 if (mac_not_zero(cfg.bridge3.macsandbox))
564 net_config_mac(cfg.bridge3.devsandbox, cfg.bridge3.macsandbox);
565 sandbox_if_up(&cfg.bridge3);
566
567 // add a default route
568 if (cfg.defaultgw) {
569 // set the default route
570 if (net_add_route(0, 0, cfg.defaultgw))
571 fprintf(stderr, "Warning: cannot configure default route\n");
572 }
573
574 // enable interfaces
575 if (cfg.interface0.configured && cfg.interface0.ip) {
576 if (arg_debug)
577 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface0.ip), cfg.interface0.dev);
578 net_if_ip(cfg.interface0.dev, cfg.interface0.ip, cfg.interface0.mask, cfg.interface0.mtu);
579 net_if_up(cfg.interface0.dev);
580 }
581 if (cfg.interface1.configured && cfg.interface1.ip) {
582 if (arg_debug)
583 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface1.ip), cfg.interface1.dev);
584 net_if_ip(cfg.interface1.dev, cfg.interface1.ip, cfg.interface1.mask, cfg.interface1.mtu);
585 net_if_up(cfg.interface1.dev);
586 }
587 if (cfg.interface2.configured && cfg.interface2.ip) {
588 if (arg_debug)
589 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface2.ip), cfg.interface2.dev);
590 net_if_ip(cfg.interface2.dev, cfg.interface2.ip, cfg.interface2.mask, cfg.interface2.mtu);
591 net_if_up(cfg.interface2.dev);
592 }
593 if (cfg.interface3.configured && cfg.interface3.ip) {
594 if (arg_debug)
595 printf("Configuring %d.%d.%d.%d address on interface %s\n", PRINT_IP(cfg.interface3.ip), cfg.interface3.dev);
596 net_if_ip(cfg.interface3.dev, cfg.interface3.ip, cfg.interface3.mask, cfg.interface3.mtu);
597 net_if_up(cfg.interface3.dev);
598 }
599
600 if (arg_debug)
601 printf("Network namespace enabled\n");
602 }
603
604 // if any dns server is configured, it is time to set it now
605 fs_resolvconf(); 764 fs_resolvconf();
765
766 //****************************
767 // fs post-processing
768 //****************************
769 preproc_delete_cp_command();
606 fs_logger_print(); 770 fs_logger_print();
607 fs_logger_change_owner(); 771 fs_logger_change_owner();
608 772
609 // print network configuration
610 if (!arg_quiet) {
611 if (any_bridge_configured() || any_interface_configured() || cfg.defaultgw || cfg.dns1) {
612 printf("\n");
613 if (any_bridge_configured() || any_interface_configured())
614 net_ifprint();
615 if (cfg.defaultgw != 0)
616 printf("Default gateway %d.%d.%d.%d\n", PRINT_IP(cfg.defaultgw));
617 if (cfg.dns1 != 0)
618 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns1));
619 if (cfg.dns2 != 0)
620 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns2));
621 if (cfg.dns3 != 0)
622 printf("DNS server %d.%d.%d.%d\n", PRINT_IP(cfg.dns3));
623 printf("\n");
624 }
625 }
626
627 fs_delete_cp_command();
628
629 //**************************** 773 //****************************
630 // set application environment 774 // set application environment
631 //**************************** 775 //****************************
@@ -649,12 +793,6 @@ int sandbox(void* sandbox_arg) {
649 } 793 }
650 } 794 }
651 795
652 // set environment
653 env_defaults();
654
655 // set user-supplied environment variables
656 env_apply();
657
658 // set nice 796 // set nice
659 if (arg_nice) { 797 if (arg_nice) {
660 errno = 0; 798 errno = 0;
@@ -668,6 +806,8 @@ int sandbox(void* sandbox_arg) {
668 806
669 // clean /tmp/.X11-unix sockets 807 // clean /tmp/.X11-unix sockets
670 fs_x11(); 808 fs_x11();
809 if (arg_x11_xorg)
810 x11_xorg();
671 811
672 //**************************** 812 //****************************
673 // set security filters 813 // set security filters
@@ -679,35 +819,35 @@ int sandbox(void* sandbox_arg) {
679 // set rlimits 819 // set rlimits
680 set_rlimits(); 820 set_rlimits();
681 821
682 // 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
683#ifdef HAVE_SECCOMP 833#ifdef HAVE_SECCOMP
684 // install protocol filter 834 // install protocol filter
685 if (cfg.protocol) { 835 if (cfg.protocol) {
686 protocol_filter(); // install filter 836 if (arg_debug)
687 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
688 } 840 }
689 841
690 // if a keep list is available, disregard the drop list 842 // if a keep list is available, disregard the drop list
691 if (arg_seccomp == 1) { 843 if (arg_seccomp == 1) {
692 if (cfg.seccomp_list_keep) 844 if (cfg.seccomp_list_keep)
693 seccomp_filter_keep(); 845 seccomp_filter_keep();
694 else if (cfg.seccomp_list_errno)
695 seccomp_filter_errno();
696 else 846 else
697 seccomp_filter_drop(enforce_seccomp); 847 seccomp_filter_drop(enforce_seccomp);
698 } 848 }
699#endif 849#endif
700 850
701 // set cpu affinity
702 if (cfg.cpus) {
703 save_cpu(); // save cpu affinity mask to CPU_CFG file
704 set_cpu_affinity();
705 }
706
707 // save cgroup in CGROUP_CFG file
708 if (cfg.cgroup)
709 save_cgroup();
710
711 //**************************************** 851 //****************************************
712 // drop privileges or create a new user namespace 852 // drop privileges or create a new user namespace
713 //**************************************** 853 //****************************************
@@ -715,7 +855,7 @@ int sandbox(void* sandbox_arg) {
715 if (arg_noroot) { 855 if (arg_noroot) {
716 int rv = unshare(CLONE_NEWUSER); 856 int rv = unshare(CLONE_NEWUSER);
717 if (rv == -1) { 857 if (rv == -1) {
718 fprintf(stderr, "Warning: cannot mount a new user namespace, going forward without it...\n"); 858 fprintf(stderr, "Warning: cannot create a new user namespace, going forward without it...\n");
719 drop_privs(arg_nogroups); 859 drop_privs(arg_nogroups);
720 arg_noroot = 0; 860 arg_noroot = 0;
721 } 861 }
@@ -739,6 +879,18 @@ int sandbox(void* sandbox_arg) {
739 printf("noroot user namespace installed\n"); 879 printf("noroot user namespace installed\n");
740 set_caps(); 880 set_caps();
741 } 881 }
882
883 //****************************************
884 // Set NO_NEW_PRIVS if desired
885 //****************************************
886 if (arg_nonewprivs) {
887 int no_new_privs = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
888
889 if(no_new_privs != 0)
890 fprintf(stderr, "Warning: NO_NEW_PRIVS disabled, it requires a Linux kernel version 3.5 or newer.\n");
891 else if (arg_debug)
892 printf("NO_NEW_PRIVS set\n");
893 }
742 894
743 //**************************************** 895 //****************************************
744 // fork the application and monitor it 896 // fork the application and monitor it
@@ -746,13 +898,27 @@ int sandbox(void* sandbox_arg) {
746 pid_t app_pid = fork(); 898 pid_t app_pid = fork();
747 if (app_pid == -1) 899 if (app_pid == -1)
748 errExit("fork"); 900 errExit("fork");
749 901
750 if (app_pid == 0) { 902 if (app_pid == 0) {
903#ifdef HAVE_APPARMOR
904 if (arg_apparmor) {
905 errno = 0;
906 if (aa_change_onexec("firejail-default")) {
907 fprintf(stderr, "Error: cannot confine the application using AppArmor.\n");
908 fprintf(stderr, "Maybe firejail-default AppArmor profile is not loaded into the kernel.\n");
909 fprintf(stderr, "As root, run \"aa-enforce firejail-default\" to load it.\n");
910 exit(1);
911 }
912 else if (arg_debug)
913 printf("AppArmor enabled\n");
914 }
915#endif
751 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died 916 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
752 start_application(); // start app 917 start_application(); // start app
753 } 918 }
754 919
755 int status = monitor_application(app_pid); // monitor application 920 int status = monitor_application(app_pid); // monitor application
921 flush_stdin();
756 922
757 if (WIFEXITED(status)) { 923 if (WIFEXITED(status)) {
758 // if we had a proper exit, return that exit status 924 // if we had a proper exit, return that exit status