aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/fs.c')
-rw-r--r--src/firejail/fs.c101
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
463void 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
484void fs_proc_sys_dev_boot(void) { 454void 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