diff options
Diffstat (limited to 'src/firejail/fs.c')
-rw-r--r-- | src/firejail/fs.c | 101 |
1 files changed, 26 insertions, 75 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 3a2fd8c38..7ff7e3c59 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -247,21 +247,13 @@ void fs_blacklist(void) { | |||
247 | 247 | ||
248 | // process bind command | 248 | // process bind command |
249 | if (strncmp(entry->data, "bind ", 5) == 0) { | 249 | if (strncmp(entry->data, "bind ", 5) == 0) { |
250 | struct stat s; | ||
250 | char *dname1 = entry->data + 5; | 251 | char *dname1 = entry->data + 5; |
251 | char *dname2 = split_comma(dname1); | 252 | char *dname2 = split_comma(dname1); |
252 | if (dname2 == NULL) { | 253 | if (dname2 == NULL || |
253 | fprintf(stderr, "Error: second directory missing in bind command\n"); | 254 | stat(dname1, &s) == -1 || |
254 | entry = entry->next; | 255 | stat(dname2, &s) == -1) { |
255 | continue; | 256 | fprintf(stderr, "Error: invalid bind command, directory missing\n"); |
256 | } | ||
257 | struct stat s; | ||
258 | if (stat(dname1, &s) == -1) { | ||
259 | fprintf(stderr, "Error: cannot find %s for bind command\n", dname1); | ||
260 | entry = entry->next; | ||
261 | continue; | ||
262 | } | ||
263 | if (stat(dname2, &s) == -1) { | ||
264 | fprintf(stderr, "Error: cannot find %s for bind command\n", dname2); | ||
265 | entry = entry->next; | 257 | entry = entry->next; |
266 | continue; | 258 | continue; |
267 | } | 259 | } |
@@ -410,10 +402,9 @@ void fs_rdonly(const char *dir) { | |||
410 | int rv = stat(dir, &s); | 402 | int rv = stat(dir, &s); |
411 | if (rv == 0) { | 403 | if (rv == 0) { |
412 | // mount --bind /bin /bin | 404 | // mount --bind /bin /bin |
413 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
414 | errExit("mount read-only"); | ||
415 | // mount --bind -o remount,ro /bin | 405 | // mount --bind -o remount,ro /bin |
416 | if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) | 406 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
407 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) | ||
417 | errExit("mount read-only"); | 408 | errExit("mount read-only"); |
418 | fs_logger2("read-only", dir); | 409 | fs_logger2("read-only", dir); |
419 | } | 410 | } |
@@ -428,15 +419,15 @@ static void fs_rdwr(const char *dir) { | |||
428 | // if the file is outside /home directory, allow only root user | 419 | // if the file is outside /home directory, allow only root user |
429 | uid_t u = getuid(); | 420 | uid_t u = getuid(); |
430 | if (u != 0 && s.st_uid != u) { | 421 | if (u != 0 && s.st_uid != u) { |
431 | fprintf(stderr, "Warning: you are not allowed to change %s to read-write\n", dir); | 422 | if (!arg_quiet) |
423 | fprintf(stderr, "Warning: you are not allowed to change %s to read-write\n", dir); | ||
432 | return; | 424 | return; |
433 | } | 425 | } |
434 | 426 | ||
435 | // mount --bind /bin /bin | 427 | // mount --bind /bin /bin |
436 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
437 | errExit("mount read-write"); | ||
438 | // mount --bind -o remount,rw /bin | 428 | // mount --bind -o remount,rw /bin |
439 | if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | 429 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
430 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | ||
440 | errExit("mount read-write"); | 431 | errExit("mount read-write"); |
441 | fs_logger2("read-write", dir); | 432 | fs_logger2("read-write", dir); |
442 | } | 433 | } |
@@ -449,37 +440,16 @@ void fs_noexec(const char *dir) { | |||
449 | int rv = stat(dir, &s); | 440 | int rv = stat(dir, &s); |
450 | if (rv == 0) { | 441 | if (rv == 0) { |
451 | // mount --bind /bin /bin | 442 | // mount --bind /bin /bin |
452 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
453 | errExit("mount noexec"); | ||
454 | // mount --bind -o remount,ro /bin | 443 | // mount --bind -o remount,ro /bin |
455 | if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) | 444 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
456 | errExit("mount read-only"); | 445 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) |
446 | errExit("mount noexec"); | ||
457 | fs_logger2("noexec", dir); | 447 | fs_logger2("noexec", dir); |
458 | } | 448 | } |
459 | } | 449 | } |
460 | 450 | ||
461 | 451 | ||
462 | 452 | ||
463 | void fs_rdonly_noexit(const char *dir) { | ||
464 | assert(dir); | ||
465 | // check directory exists | ||
466 | struct stat s; | ||
467 | int rv = stat(dir, &s); | ||
468 | if (rv == 0) { | ||
469 | int merr = 0; | ||
470 | // mount --bind /bin /bin | ||
471 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
472 | merr = 1; | ||
473 | // mount --bind -o remount,ro /bin | ||
474 | if (mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) | ||
475 | merr = 1; | ||
476 | if (merr) | ||
477 | fprintf(stderr, "Warning: cannot mount %s read-only\n", dir); | ||
478 | else | ||
479 | fs_logger2("read-only", dir); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | // mount /proc and /sys directories | 453 | // mount /proc and /sys directories |
484 | void fs_proc_sys_dev_boot(void) { | 454 | void fs_proc_sys_dev_boot(void) { |
485 | if (arg_debug) | 455 | if (arg_debug) |
@@ -489,10 +459,8 @@ void fs_proc_sys_dev_boot(void) { | |||
489 | fs_logger("remount /proc"); | 459 | fs_logger("remount /proc"); |
490 | 460 | ||
491 | // remount /proc/sys readonly | 461 | // remount /proc/sys readonly |
492 | if (mount("/proc/sys", "/proc/sys", NULL, MS_BIND | MS_REC, NULL) < 0) | 462 | if (mount("/proc/sys", "/proc/sys", NULL, MS_BIND | MS_REC, NULL) < 0 || |
493 | errExit("mounting /proc/sys"); | 463 | mount(NULL, "/proc/sys", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC, NULL) < 0) |
494 | |||
495 | if (mount(NULL, "/proc/sys", NULL, MS_BIND | MS_REMOUNT | MS_RDONLY | MS_REC, NULL) < 0) | ||
496 | errExit("mounting /proc/sys"); | 464 | errExit("mounting /proc/sys"); |
497 | fs_logger("read-only /proc/sys"); | 465 | fs_logger("read-only /proc/sys"); |
498 | 466 | ||
@@ -646,12 +614,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { | |||
646 | if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) | 614 | if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) |
647 | errExit("asprintf"); | 615 | errExit("asprintf"); |
648 | if (stat(dirname, &s) == -1) { | 616 | if (stat(dirname, &s) == -1) { |
649 | /* coverity[toctou] */ | 617 | mkdir_attr(dirname, 0700, 0, 0); |
650 | if (mkdir(dirname, 0700)) | ||
651 | errExit("mkdir"); | ||
652 | if (chmod(dirname, 0700) == -1) | ||
653 | errExit("chmod"); | ||
654 | ASSERT_PERMS(dirname, getuid(), getgid(), 0700); | ||
655 | } | 618 | } |
656 | else if (is_link(dirname)) { | 619 | else if (is_link(dirname)) { |
657 | fprintf(stderr, "Error: invalid ~/.firejail directory\n"); | 620 | fprintf(stderr, "Error: invalid ~/.firejail directory\n"); |
@@ -733,11 +696,7 @@ void fs_overlayfs(void) { | |||
733 | char *oroot; | 696 | char *oroot; |
734 | if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) | 697 | if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) |
735 | errExit("asprintf"); | 698 | errExit("asprintf"); |
736 | if (mkdir(oroot, 0755)) | 699 | mkdir_attr(oroot, 0755, 0, 0); |
737 | errExit("mkdir"); | ||
738 | if (chmod(oroot, 0755) == -1) | ||
739 | errExit("chmod"); | ||
740 | ASSERT_PERMS(oroot, 0, 0, 0755); | ||
741 | 700 | ||
742 | struct stat s; | 701 | struct stat s; |
743 | char *basedir = RUN_MNT_DIR; | 702 | char *basedir = RUN_MNT_DIR; |
@@ -766,11 +725,9 @@ void fs_overlayfs(void) { | |||
766 | 725 | ||
767 | // no need to check arg_overlay_reuse | 726 | // no need to check arg_overlay_reuse |
768 | if (stat(odiff, &s) != 0) { | 727 | if (stat(odiff, &s) != 0) { |
769 | if (mkdir(odiff, 0755)) | 728 | mkdir_attr(odiff, 0755, 0, 0); |
770 | errExit("mkdir"); | ||
771 | } | 729 | } |
772 | 730 | else if (set_perms(odiff, 0, 0, 0755)) | |
773 | if (set_perms(odiff, 0, 0, 0755)) | ||
774 | errExit("set_perms"); | 731 | errExit("set_perms"); |
775 | 732 | ||
776 | char *owork; | 733 | char *owork; |
@@ -779,11 +736,9 @@ void fs_overlayfs(void) { | |||
779 | 736 | ||
780 | // no need to check arg_overlay_reuse | 737 | // no need to check arg_overlay_reuse |
781 | if (stat(owork, &s) != 0) { | 738 | if (stat(owork, &s) != 0) { |
782 | if (mkdir(owork, 0755)) | 739 | mkdir_attr(owork, 0755, 0, 0); |
783 | errExit("mkdir"); | ||
784 | } | 740 | } |
785 | 741 | else if (set_perms(owork, 0, 0, 0755)) | |
786 | if (set_perms(owork, 0, 0, 0755)) | ||
787 | errExit("chown"); | 742 | errExit("chown"); |
788 | 743 | ||
789 | // mount overlayfs | 744 | // mount overlayfs |
@@ -839,11 +794,9 @@ void fs_overlayfs(void) { | |||
839 | 794 | ||
840 | // no need to check arg_overlay_reuse | 795 | // no need to check arg_overlay_reuse |
841 | if (stat(hdiff, &s) != 0) { | 796 | if (stat(hdiff, &s) != 0) { |
842 | if (mkdir(hdiff, S_IRWXU | S_IRWXG | S_IRWXO)) | 797 | mkdir_attr(hdiff, S_IRWXU | S_IRWXG | S_IRWXO, 0, 0); |
843 | errExit("mkdir"); | ||
844 | } | 798 | } |
845 | 799 | else if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | |
846 | if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | ||
847 | errExit("set_perms"); | 800 | errExit("set_perms"); |
848 | 801 | ||
849 | if(asprintf(&hwork, "%s/hwork", basedir) == -1) | 802 | if(asprintf(&hwork, "%s/hwork", basedir) == -1) |
@@ -851,11 +804,9 @@ void fs_overlayfs(void) { | |||
851 | 804 | ||
852 | // no need to check arg_overlay_reuse | 805 | // no need to check arg_overlay_reuse |
853 | if (stat(hwork, &s) != 0) { | 806 | if (stat(hwork, &s) != 0) { |
854 | if (mkdir(hwork, S_IRWXU | S_IRWXG | S_IRWXO)) | 807 | mkdir_attr(hwork, S_IRWXU | S_IRWXG | S_IRWXO, 0, 0); |
855 | errExit("mkdir"); | ||
856 | } | 808 | } |
857 | 809 | else if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | |
858 | if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | ||
859 | errExit("set_perms"); | 810 | errExit("set_perms"); |
860 | 811 | ||
861 | // no homedir in overlay so now mount another overlay for /home | 812 | // no homedir in overlay so now mount another overlay for /home |