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.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index eaf23e603..01182bd2c 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -57,6 +57,7 @@ static char *opstr[] = {
57static void disable_file(OPERATION op, const char *filename) { 57static void disable_file(OPERATION op, const char *filename) {
58 assert(filename); 58 assert(filename);
59 assert(op <OPERATION_MAX); 59 assert(op <OPERATION_MAX);
60 EUID_ASSERT();
60 61
61 // Resolve all symlinks 62 // Resolve all symlinks
62 char* fname = realpath(filename, NULL); 63 char* fname = realpath(filename, NULL);
@@ -74,9 +75,11 @@ static void disable_file(OPERATION op, const char *filename) {
74 return; 75 return;
75 } 76 }
76 77
78 EUID_ROOT();
77 int err = bind_mount_path_to_fd(RUN_RO_DIR, fd); 79 int err = bind_mount_path_to_fd(RUN_RO_DIR, fd);
78 if (err < 0) 80 if (err < 0)
79 err = bind_mount_path_to_fd(RUN_RO_FILE, fd); 81 err = bind_mount_path_to_fd(RUN_RO_FILE, fd);
82 EUID_USER();
80 close(fd); 83 close(fd);
81 84
82 if (err == 0) { 85 if (err == 0) {
@@ -142,6 +145,7 @@ static void disable_file(OPERATION op, const char *filename) {
142 free(fname); 145 free(fname);
143 return; 146 return;
144 } 147 }
148 EUID_ROOT();
145 if (S_ISDIR(s.st_mode)) { 149 if (S_ISDIR(s.st_mode)) {
146 if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0) 150 if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0)
147 errExit("disable file"); 151 errExit("disable file");
@@ -150,6 +154,7 @@ static void disable_file(OPERATION op, const char *filename) {
150 if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0) 154 if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0)
151 errExit("disable file"); 155 errExit("disable file");
152 } 156 }
157 EUID_USER();
153 close(fd); 158 close(fd);
154 159
155 if (op == BLACKLIST_FILE) 160 if (op == BLACKLIST_FILE)
@@ -170,8 +175,10 @@ static void disable_file(OPERATION op, const char *filename) {
170 exit(1); 175 exit(1);
171 } 176 }
172 } 177 }
178 // fs_tmpfs returns with EUID 0
173 fs_tmpfs(fname, getuid()); 179 fs_tmpfs(fname, getuid());
174 selinux_relabel_path(fname, fname); 180 selinux_relabel_path(fname, fname);
181 EUID_USER();
175 } 182 }
176 else 183 else
177 fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname); 184 fwarning("%s is not a directory; cannot mount a tmpfs on top of it.\n", fname);
@@ -191,6 +198,7 @@ static int *nbcheck = NULL;
191// Treat pattern as a shell glob pattern and blacklist matching files 198// Treat pattern as a shell glob pattern and blacklist matching files
192static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len) { 199static void globbing(OPERATION op, const char *pattern, const char *noblacklist[], size_t noblacklist_len) {
193 assert(pattern); 200 assert(pattern);
201 EUID_ASSERT();
194 202
195#ifdef TEST_NO_BLACKLIST_MATCHING 203#ifdef TEST_NO_BLACKLIST_MATCHING
196 if (nbcheck_start == 0) { 204 if (nbcheck_start == 0) {
@@ -264,6 +272,7 @@ void fs_blacklist(void) {
264 if (noblacklist == NULL) 272 if (noblacklist == NULL)
265 errExit("failed allocating memory for noblacklist entries"); 273 errExit("failed allocating memory for noblacklist entries");
266 274
275 EUID_USER();
267 while (entry) { 276 while (entry) {
268 OPERATION op = OPERATION_MAX; 277 OPERATION op = OPERATION_MAX;
269 char *ptr; 278 char *ptr;
@@ -294,11 +303,13 @@ void fs_blacklist(void) {
294 if (arg_debug) 303 if (arg_debug)
295 printf("Mount-bind %s on top of %s\n", dname1, dname2); 304 printf("Mount-bind %s on top of %s\n", dname1, dname2);
296 // preserve dname2 mode and ownership 305 // preserve dname2 mode and ownership
306 // EUID_ROOT(); - option not accessible to non-root users
297 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0) 307 if (mount(dname1, dname2, NULL, MS_BIND|MS_REC, NULL) < 0)
298 errExit("mount bind"); 308 errExit("mount bind");
299 /* coverity[toctou] */ 309 /* coverity[toctou] */
300 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode)) 310 if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode))
301 errExit("set_perms"); 311 errExit("set_perms");
312 // EUID_USER();
302 313
303 entry = entry->next; 314 entry = entry->next;
304 continue; 315 continue;
@@ -376,16 +387,12 @@ void fs_blacklist(void) {
376 op = MOUNT_TMPFS; 387 op = MOUNT_TMPFS;
377 } 388 }
378 else if (strncmp(entry->data, "mkdir ", 6) == 0) { 389 else if (strncmp(entry->data, "mkdir ", 6) == 0) {
379 EUID_USER();
380 fs_mkdir(entry->data + 6); 390 fs_mkdir(entry->data + 6);
381 EUID_ROOT();
382 entry = entry->next; 391 entry = entry->next;
383 continue; 392 continue;
384 } 393 }
385 else if (strncmp(entry->data, "mkfile ", 7) == 0) { 394 else if (strncmp(entry->data, "mkfile ", 7) == 0) {
386 EUID_USER();
387 fs_mkfile(entry->data + 7); 395 fs_mkfile(entry->data + 7);
388 EUID_ROOT();
389 entry = entry->next; 396 entry = entry->next;
390 continue; 397 continue;
391 } 398 }
@@ -441,6 +448,8 @@ void fs_blacklist(void) {
441 for (i = 0; i < noblacklist_c; i++) 448 for (i = 0; i < noblacklist_c; i++)
442 free(noblacklist[i]); 449 free(noblacklist[i]);
443 free(noblacklist); 450 free(noblacklist);
451
452 EUID_ROOT();
444} 453}
445 454
446//*********************************************** 455//***********************************************
@@ -449,6 +458,7 @@ void fs_blacklist(void) {
449 458
450// mount a writable tmpfs on directory; requires a resolved path 459// mount a writable tmpfs on directory; requires a resolved path
451void fs_tmpfs(const char *dir, unsigned check_owner) { 460void fs_tmpfs(const char *dir, unsigned check_owner) {
461 EUID_USER();
452 assert(dir); 462 assert(dir);
453 if (arg_debug) 463 if (arg_debug)
454 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no"); 464 printf("Mounting tmpfs on %s, check owner: %s\n", dir, (check_owner)? "yes": "no");
@@ -473,6 +483,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
473 errExit("fstatvfs"); 483 errExit("fstatvfs");
474 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND); 484 unsigned long flags = buf.f_flag & ~(MS_RDONLY|MS_BIND);
475 // mount via the symbolic link in /proc/self/fd 485 // mount via the symbolic link in /proc/self/fd
486 EUID_ROOT();
476 char *proc; 487 char *proc;
477 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1) 488 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
478 errExit("asprintf"); 489 errExit("asprintf");
@@ -490,6 +501,7 @@ void fs_tmpfs(const char *dir, unsigned check_owner) {
490 501
491// remount path, preserving other mount flags; requires a resolved path 502// remount path, preserving other mount flags; requires a resolved path
492static void fs_remount_simple(const char *path, OPERATION op) { 503static void fs_remount_simple(const char *path, OPERATION op) {
504 EUID_ASSERT();
493 assert(path); 505 assert(path);
494 506
495 // open path without following symbolic links 507 // open path without following symbolic links
@@ -555,7 +567,9 @@ static void fs_remount_simple(const char *path, OPERATION op) {
555 567
556 // make path a mount point: 568 // make path a mount point:
557 // mount --bind path path 569 // mount --bind path path
570 EUID_ROOT();
558 int err = bind_mount_by_fd(fd, fd); 571 int err = bind_mount_by_fd(fd, fd);
572 EUID_USER();
559 if (err) { 573 if (err) {
560 close(fd); 574 close(fd);
561 goto out; 575 goto out;
@@ -575,7 +589,9 @@ static void fs_remount_simple(const char *path, OPERATION op) {
575 if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino) 589 if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino)
576 errLogExit("invalid %s mount", opstr[op]); 590 errLogExit("invalid %s mount", opstr[op]);
577 591
592 EUID_ROOT();
578 err = remount_by_fd(fd2, flags); 593 err = remount_by_fd(fd2, flags);
594 EUID_USER();
579 close(fd2); 595 close(fd2);
580 if (err) 596 if (err)
581 goto out; 597 goto out;
@@ -599,7 +615,9 @@ out:
599 615
600// remount recursively; requires a resolved path 616// remount recursively; requires a resolved path
601static void fs_remount_rec(const char *dir, OPERATION op) { 617static void fs_remount_rec(const char *dir, OPERATION op) {
618 EUID_ASSERT();
602 assert(dir); 619 assert(dir);
620
603 struct stat s; 621 struct stat s;
604 if (stat(dir, &s) != 0) 622 if (stat(dir, &s) != 0)
605 return; 623 return;
@@ -637,6 +655,9 @@ static void fs_remount_rec(const char *dir, OPERATION op) {
637// resolve a path and remount it 655// resolve a path and remount it
638void fs_remount(const char *path, OPERATION op, int rec) { 656void fs_remount(const char *path, OPERATION op, int rec) {
639 assert(path); 657 assert(path);
658 assert(geteuid() == 0);
659 EUID_USER();
660
640 char *rpath = realpath(path, NULL); 661 char *rpath = realpath(path, NULL);
641 if (rpath) { 662 if (rpath) {
642 if (rec) 663 if (rec)
@@ -645,10 +666,12 @@ void fs_remount(const char *path, OPERATION op, int rec) {
645 fs_remount_simple(rpath, op); 666 fs_remount_simple(rpath, op);
646 free(rpath); 667 free(rpath);
647 } 668 }
669 EUID_ROOT();
648} 670}
649 671
650// Disable /mnt, /media, /run/mount and /run/media access 672// Disable /mnt, /media, /run/mount and /run/media access
651void fs_mnt(const int enforce) { 673void fs_mnt(const int enforce) {
674 EUID_USER();
652 if (enforce) { 675 if (enforce) {
653 // disable-mnt set in firejail.config 676 // disable-mnt set in firejail.config
654 // overriding with noblacklist is not possible in this case 677 // overriding with noblacklist is not possible in this case
@@ -658,13 +681,12 @@ void fs_mnt(const int enforce) {
658 disable_file(BLACKLIST_FILE, "/run/media"); 681 disable_file(BLACKLIST_FILE, "/run/media");
659 } 682 }
660 else { 683 else {
661 EUID_USER();
662 profile_add("blacklist /mnt"); 684 profile_add("blacklist /mnt");
663 profile_add("blacklist /media"); 685 profile_add("blacklist /media");
664 profile_add("blacklist /run/mount"); 686 profile_add("blacklist /run/mount");
665 profile_add("blacklist /run/media"); 687 profile_add("blacklist /run/media");
666 EUID_ROOT();
667 } 688 }
689 EUID_ROOT();
668} 690}
669 691
670 692
@@ -679,7 +701,6 @@ void fs_proc_sys_dev_boot(void) {
679 errExit("mounting /proc/sys"); 701 errExit("mounting /proc/sys");
680 fs_logger("read-only /proc/sys"); 702 fs_logger("read-only /proc/sys");
681 703
682
683 /* Mount a version of /sys that describes the network namespace */ 704 /* Mount a version of /sys that describes the network namespace */
684 if (arg_debug) 705 if (arg_debug)
685 printf("Remounting /sys directory\n"); 706 printf("Remounting /sys directory\n");
@@ -694,13 +715,13 @@ void fs_proc_sys_dev_boot(void) {
694 else 715 else
695 fs_logger("remount /sys"); 716 fs_logger("remount /sys");
696 717
718 EUID_USER();
719
697 disable_file(BLACKLIST_FILE, "/sys/firmware"); 720 disable_file(BLACKLIST_FILE, "/sys/firmware");
698 disable_file(BLACKLIST_FILE, "/sys/hypervisor"); 721 disable_file(BLACKLIST_FILE, "/sys/hypervisor");
699 { // allow user access to some directories in /sys/ by specifying 'noblacklist' option 722 { // allow user access to some directories in /sys/ by specifying 'noblacklist' option
700 EUID_USER();
701 profile_add("blacklist /sys/fs"); 723 profile_add("blacklist /sys/fs");
702 profile_add("blacklist /sys/module"); 724 profile_add("blacklist /sys/module");
703 EUID_ROOT();
704 } 725 }
705 disable_file(BLACKLIST_FILE, "/sys/power"); 726 disable_file(BLACKLIST_FILE, "/sys/power");
706 disable_file(BLACKLIST_FILE, "/sys/kernel/debug"); 727 disable_file(BLACKLIST_FILE, "/sys/kernel/debug");
@@ -744,8 +765,6 @@ void fs_proc_sys_dev_boot(void) {
744 // disable /dev/port 765 // disable /dev/port
745 disable_file(BLACKLIST_FILE, "/dev/port"); 766 disable_file(BLACKLIST_FILE, "/dev/port");
746 767
747
748
749 // disable various ipc sockets in /run/user 768 // disable various ipc sockets in /run/user
750 if (!arg_writable_run_user) { 769 if (!arg_writable_run_user) {
751 char *fname; 770 char *fname;
@@ -778,10 +797,13 @@ void fs_proc_sys_dev_boot(void) {
778 disable_file(BLACKLIST_FILE, "/dev/kmsg"); 797 disable_file(BLACKLIST_FILE, "/dev/kmsg");
779 disable_file(BLACKLIST_FILE, "/proc/kmsg"); 798 disable_file(BLACKLIST_FILE, "/proc/kmsg");
780 } 799 }
800
801 EUID_ROOT();
781} 802}
782 803
783// disable firejail configuration in ~/.config/firejail 804// disable firejail configuration in ~/.config/firejail
784void disable_config(void) { 805void disable_config(void) {
806 EUID_USER();
785 char *fname; 807 char *fname;
786 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1) 808 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1)
787 errExit("asprintf"); 809 errExit("asprintf");
@@ -794,6 +816,7 @@ void disable_config(void) {
794 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR); 816 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR);
795 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR); 817 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
796 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR); 818 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
819 EUID_ROOT();
797} 820}
798 821
799 822
@@ -855,6 +878,7 @@ void fs_basic_fs(void) {
855#ifdef HAVE_OVERLAYFS 878#ifdef HAVE_OVERLAYFS
856char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { 879char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
857 assert(subdirname); 880 assert(subdirname);
881 EUID_ASSERT();
858 struct stat s; 882 struct stat s;
859 char *dirname; 883 char *dirname;
860 884
@@ -1214,6 +1238,7 @@ void fs_overlayfs(void) {
1214 1238
1215// this function is called from sandbox.c before blacklist/whitelist functions 1239// this function is called from sandbox.c before blacklist/whitelist functions
1216void fs_private_tmp(void) { 1240void fs_private_tmp(void) {
1241 EUID_ASSERT();
1217 if (arg_debug) 1242 if (arg_debug)
1218 printf("Generate private-tmp whitelist commands\n"); 1243 printf("Generate private-tmp whitelist commands\n");
1219 1244