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.c210
1 files changed, 114 insertions, 96 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 09de11de9..01182bd2c 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -54,16 +54,10 @@ static char *opstr[] = {
54 [MOUNT_RDWR_NOCHECK] = "read-write", 54 [MOUNT_RDWR_NOCHECK] = "read-write",
55}; 55};
56 56
57typedef enum {
58 UNSUCCESSFUL,
59 SUCCESSFUL
60} LAST_DISABLE_OPERATION;
61LAST_DISABLE_OPERATION last_disable = UNSUCCESSFUL;
62
63static void disable_file(OPERATION op, const char *filename) { 57static void disable_file(OPERATION op, const char *filename) {
64 assert(filename); 58 assert(filename);
65 assert(op <OPERATION_MAX); 59 assert(op <OPERATION_MAX);
66 last_disable = UNSUCCESSFUL; 60 EUID_ASSERT();
67 61
68 // Resolve all symlinks 62 // Resolve all symlinks
69 char* fname = realpath(filename, NULL); 63 char* fname = realpath(filename, NULL);
@@ -71,20 +65,24 @@ static void disable_file(OPERATION op, const char *filename) {
71 return; 65 return;
72 } 66 }
73 if (fname == NULL && errno == EACCES) { 67 if (fname == NULL && errno == EACCES) {
74 if (arg_debug)
75 printf("Debug: no access to file %s, forcing mount\n", filename);
76 // realpath and stat functions will fail on FUSE filesystems 68 // realpath and stat functions will fail on FUSE filesystems
77 // they don't seem to like a uid of 0 69 // they don't seem to like a uid of 0
78 // force mounting 70 // force mounting
79 int rv = mount(RUN_RO_DIR, filename, "none", MS_BIND, "mode=400,gid=0"); 71 int fd = open(filename, O_PATH|O_CLOEXEC);
80 if (rv == 0) 72 if (fd < 0) {
81 last_disable = SUCCESSFUL; 73 if (arg_debug)
82 else { 74 printf("Warning (blacklisting): cannot open %s: %s\n", filename, strerror(errno));
83 rv = mount(RUN_RO_FILE, filename, "none", MS_BIND, "mode=400,gid=0"); 75 return;
84 if (rv == 0)
85 last_disable = SUCCESSFUL;
86 } 76 }
87 if (last_disable == SUCCESSFUL) { 77
78 EUID_ROOT();
79 int err = bind_mount_path_to_fd(RUN_RO_DIR, fd);
80 if (err < 0)
81 err = bind_mount_path_to_fd(RUN_RO_FILE, fd);
82 EUID_USER();
83 close(fd);
84
85 if (err == 0) {
88 if (arg_debug) 86 if (arg_debug)
89 printf("Disable %s\n", filename); 87 printf("Disable %s\n", filename);
90 if (op == BLACKLIST_FILE) 88 if (op == BLACKLIST_FILE)
@@ -92,21 +90,18 @@ static void disable_file(OPERATION op, const char *filename) {
92 else 90 else
93 fs_logger2("blacklist-nolog", filename); 91 fs_logger2("blacklist-nolog", filename);
94 } 92 }
95 else { 93 else if (arg_debug)
96 if (arg_debug) 94 printf("Warning (blacklisting): cannot mount on %s\n", filename);
97 printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename);
98 }
99 95
100 return; 96 return;
101 } 97 }
102 98
103 // if the file is not present, do nothing 99 // if the file is not present, do nothing
100 assert(fname);
104 struct stat s; 101 struct stat s;
105 if (fname == NULL) 102 if (stat(fname, &s) < 0) {
106 return;
107 if (stat(fname, &s) == -1) {
108 if (arg_debug) 103 if (arg_debug)
109 fwarning("%s does not exist, skipping...\n", fname); 104 printf("Warning (blacklisting): cannot access %s: %s\n", fname, strerror(errno));
110 free(fname); 105 free(fname);
111 return; 106 return;
112 } 107 }
@@ -115,8 +110,10 @@ static void disable_file(OPERATION op, const char *filename) {
115 // we migth have a file found in ${PATH} pointing to /usr/bin/firejail 110 // we migth have a file found in ${PATH} pointing to /usr/bin/firejail
116 // blacklisting it here will end up breaking situations like user clicks on a link in Thunderbird 111 // blacklisting it here will end up breaking situations like user clicks on a link in Thunderbird
117 // and expects Firefox to open in the same sandbox 112 // and expects Firefox to open in the same sandbox
118 if (strcmp(BINDIR "/firejail", fname) == 0) 113 if (strcmp(BINDIR "/firejail", fname) == 0) {
114 free(fname);
119 return; 115 return;
116 }
120 117
121 // modify the file 118 // modify the file
122 if (op == BLACKLIST_FILE || op == BLACKLIST_NOLOG) { 119 if (op == BLACKLIST_FILE || op == BLACKLIST_NOLOG) {
@@ -141,15 +138,25 @@ static void disable_file(OPERATION op, const char *filename) {
141 printf(" - no logging\n"); 138 printf(" - no logging\n");
142 } 139 }
143 140
141 int fd = open(fname, O_PATH|O_CLOEXEC);
142 if (fd < 0) {
143 if (arg_debug)
144 printf("Warning (blacklisting): cannot open %s: %s\n", fname, strerror(errno));
145 free(fname);
146 return;
147 }
148 EUID_ROOT();
144 if (S_ISDIR(s.st_mode)) { 149 if (S_ISDIR(s.st_mode)) {
145 if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 150 if (bind_mount_path_to_fd(RUN_RO_DIR, fd) < 0)
146 errExit("disable file"); 151 errExit("disable file");
147 } 152 }
148 else { 153 else {
149 if (mount(RUN_RO_FILE, fname, "none", MS_BIND, "mode=400,gid=0") < 0) 154 if (bind_mount_path_to_fd(RUN_RO_FILE, fd) < 0)
150 errExit("disable file"); 155 errExit("disable file");
151 } 156 }
152 last_disable = SUCCESSFUL; 157 EUID_USER();
158 close(fd);
159
153 if (op == BLACKLIST_FILE) 160 if (op == BLACKLIST_FILE)
154 fs_logger2("blacklist", fname); 161 fs_logger2("blacklist", fname);
155 else 162 else
@@ -158,7 +165,6 @@ static void disable_file(OPERATION op, const char *filename) {
158 } 165 }
159 else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) { 166 else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) {
160 fs_remount_rec(fname, op); 167 fs_remount_rec(fname, op);
161 // todo: last_disable = SUCCESSFUL;
162 } 168 }
163 else if (op == MOUNT_TMPFS) { 169 else if (op == MOUNT_TMPFS) {
164 if (S_ISDIR(s.st_mode)) { 170 if (S_ISDIR(s.st_mode)) {
@@ -169,9 +175,10 @@ static void disable_file(OPERATION op, const char *filename) {
169 exit(1); 175 exit(1);
170 } 176 }
171 } 177 }
178 // fs_tmpfs returns with EUID 0
172 fs_tmpfs(fname, getuid()); 179 fs_tmpfs(fname, getuid());
173 selinux_relabel_path(fname, fname); 180 selinux_relabel_path(fname, fname);
174 last_disable = SUCCESSFUL; 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,38 +501,42 @@ 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
496 int fd1 = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC); 508 int fd = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
497 if (fd1 == -1) 509 if (fd < 0)
498 goto out; 510 goto out;
499 struct stat s1; 511
500 if (fstat(fd1, &s1) == -1) { 512 struct stat s;
513 if (fstat(fd, &s) < 0) {
501 // fstat can fail with EACCES if path is a FUSE mount, 514 // fstat can fail with EACCES if path is a FUSE mount,
502 // mounted without 'allow_root' or 'allow_other' 515 // mounted without 'allow_root' or 'allow_other'
503 if (errno != EACCES) 516 if (errno != EACCES)
504 errExit("fstat"); 517 errExit("fstat");
505 close(fd1); 518 close(fd);
506 goto out; 519 goto out;
507 } 520 }
508 // get mount flags 521 // get mount flags
509 struct statvfs buf; 522 struct statvfs buf;
510 if (fstatvfs(fd1, &buf) == -1) 523 if (fstatvfs(fd, &buf) < 0) {
511 errExit("fstatvfs"); 524 close(fd);
525 goto out;
526 }
512 unsigned long flags = buf.f_flag; 527 unsigned long flags = buf.f_flag;
513 528
514 // read-write option 529 // read-write option
515 if (op == MOUNT_RDWR || op == MOUNT_RDWR_NOCHECK) { 530 if (op == MOUNT_RDWR || op == MOUNT_RDWR_NOCHECK) {
516 // nothing to do if there is no read-only flag 531 // nothing to do if there is no read-only flag
517 if ((flags & MS_RDONLY) == 0) { 532 if ((flags & MS_RDONLY) == 0) {
518 close(fd1); 533 close(fd);
519 return; 534 return;
520 } 535 }
521 // allow only user owned directories, except the user is root 536 // allow only user owned directories, except the user is root
522 if (op != MOUNT_RDWR_NOCHECK && getuid() != 0 && s1.st_uid != getuid()) { 537 if (op != MOUNT_RDWR_NOCHECK && getuid() != 0 && s.st_uid != getuid()) {
523 fwarning("you are not allowed to change %s to read-write\n", path); 538 fwarning("you are not allowed to change %s to read-write\n", path);
524 close(fd1); 539 close(fd);
525 return; 540 return;
526 } 541 }
527 flags &= ~MS_RDONLY; 542 flags &= ~MS_RDONLY;
@@ -530,7 +545,7 @@ static void fs_remount_simple(const char *path, OPERATION op) {
530 else if (op == MOUNT_NOEXEC) { 545 else if (op == MOUNT_NOEXEC) {
531 // nothing to do if path is mounted noexec already 546 // nothing to do if path is mounted noexec already
532 if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID)) { 547 if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID)) {
533 close(fd1); 548 close(fd);
534 return; 549 return;
535 } 550 }
536 flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID; 551 flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID;
@@ -539,7 +554,7 @@ static void fs_remount_simple(const char *path, OPERATION op) {
539 else if (op == MOUNT_READONLY) { 554 else if (op == MOUNT_READONLY) {
540 // nothing to do if path is mounted read-only already 555 // nothing to do if path is mounted read-only already
541 if ((flags & MS_RDONLY) == MS_RDONLY) { 556 if ((flags & MS_RDONLY) == MS_RDONLY) {
542 close(fd1); 557 close(fd);
543 return; 558 return;
544 } 559 }
545 flags |= MS_RDONLY; 560 flags |= MS_RDONLY;
@@ -549,29 +564,37 @@ static void fs_remount_simple(const char *path, OPERATION op) {
549 564
550 if (arg_debug) 565 if (arg_debug)
551 printf("Mounting %s %s\n", opstr[op], path); 566 printf("Mounting %s %s\n", opstr[op], path);
567
568 // make path a mount point:
552 // mount --bind path path 569 // mount --bind path path
553 char *proc; 570 EUID_ROOT();
554 if (asprintf(&proc, "/proc/self/fd/%d", fd1) == -1) 571 int err = bind_mount_by_fd(fd, fd);
555 errExit("asprintf"); 572 EUID_USER();
556 if (mount(proc, proc, NULL, MS_BIND|MS_REC, NULL) < 0) 573 if (err) {
557 errExit("mount"); 574 close(fd);
558 free(proc); 575 goto out;
576 }
559 577
560 // mount --bind -o remount,ro path 578 // remount the mount point
561 // need to open path again without following symbolic links 579 // need to open path again
562 int fd2 = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC); 580 int fd2 = safer_openat(-1, path, O_PATH|O_NOFOLLOW|O_CLOEXEC);
563 if (fd2 == -1) 581 close(fd); // earliest timepoint to close fd
564 errExit("open"); 582 if (fd2 < 0)
583 goto out;
584
585 // device and inode number should be the same
565 struct stat s2; 586 struct stat s2;
566 if (fstat(fd2, &s2) == -1) 587 if (fstat(fd2, &s2) < 0)
567 errExit("fstat"); 588 errExit("fstat");
568 // device and inode number should be the same 589 if (s.st_dev != s2.st_dev || s.st_ino != s2.st_ino)
569 if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino)
570 errLogExit("invalid %s mount", opstr[op]); 590 errLogExit("invalid %s mount", opstr[op]);
571 if (asprintf(&proc, "/proc/self/fd/%d", fd2) == -1) 591
572 errExit("asprintf"); 592 EUID_ROOT();
573 if (mount(NULL, proc, NULL, flags|MS_BIND|MS_REMOUNT, NULL) < 0) 593 err = remount_by_fd(fd2, flags);
574 errExit("mount"); 594 EUID_USER();
595 close(fd2);
596 if (err)
597 goto out;
575 598
576 // run a sanity check on /proc/self/mountinfo and confirm that target of the last 599 // run a sanity check on /proc/self/mountinfo and confirm that target of the last
577 // mount operation was path; if there are other mount points contained inside path, 600 // mount operation was path; if there are other mount points contained inside path,
@@ -582,10 +605,8 @@ static void fs_remount_simple(const char *path, OPERATION op) {
582 (*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/')) 605 (*(mptr->dir + len) != '\0' && *(mptr->dir + len) != '/'))
583 && strcmp(path, "/") != 0) // support read-only=/ 606 && strcmp(path, "/") != 0) // support read-only=/
584 errLogExit("invalid %s mount", opstr[op]); 607 errLogExit("invalid %s mount", opstr[op]);
608
585 fs_logger2(opstr[op], path); 609 fs_logger2(opstr[op], path);
586 free(proc);
587 close(fd1);
588 close(fd2);
589 return; 610 return;
590 611
591out: 612out:
@@ -594,7 +615,9 @@ out:
594 615
595// remount recursively; requires a resolved path 616// remount recursively; requires a resolved path
596static void fs_remount_rec(const char *dir, OPERATION op) { 617static void fs_remount_rec(const char *dir, OPERATION op) {
618 EUID_ASSERT();
597 assert(dir); 619 assert(dir);
620
598 struct stat s; 621 struct stat s;
599 if (stat(dir, &s) != 0) 622 if (stat(dir, &s) != 0)
600 return; 623 return;
@@ -632,6 +655,9 @@ static void fs_remount_rec(const char *dir, OPERATION op) {
632// resolve a path and remount it 655// resolve a path and remount it
633void fs_remount(const char *path, OPERATION op, int rec) { 656void fs_remount(const char *path, OPERATION op, int rec) {
634 assert(path); 657 assert(path);
658 assert(geteuid() == 0);
659 EUID_USER();
660
635 char *rpath = realpath(path, NULL); 661 char *rpath = realpath(path, NULL);
636 if (rpath) { 662 if (rpath) {
637 if (rec) 663 if (rec)
@@ -640,10 +666,12 @@ void fs_remount(const char *path, OPERATION op, int rec) {
640 fs_remount_simple(rpath, op); 666 fs_remount_simple(rpath, op);
641 free(rpath); 667 free(rpath);
642 } 668 }
669 EUID_ROOT();
643} 670}
644 671
645// Disable /mnt, /media, /run/mount and /run/media access 672// Disable /mnt, /media, /run/mount and /run/media access
646void fs_mnt(const int enforce) { 673void fs_mnt(const int enforce) {
674 EUID_USER();
647 if (enforce) { 675 if (enforce) {
648 // disable-mnt set in firejail.config 676 // disable-mnt set in firejail.config
649 // overriding with noblacklist is not possible in this case 677 // overriding with noblacklist is not possible in this case
@@ -653,13 +681,12 @@ void fs_mnt(const int enforce) {
653 disable_file(BLACKLIST_FILE, "/run/media"); 681 disable_file(BLACKLIST_FILE, "/run/media");
654 } 682 }
655 else { 683 else {
656 EUID_USER();
657 profile_add("blacklist /mnt"); 684 profile_add("blacklist /mnt");
658 profile_add("blacklist /media"); 685 profile_add("blacklist /media");
659 profile_add("blacklist /run/mount"); 686 profile_add("blacklist /run/mount");
660 profile_add("blacklist /run/media"); 687 profile_add("blacklist /run/media");
661 EUID_ROOT();
662 } 688 }
689 EUID_ROOT();
663} 690}
664 691
665 692
@@ -674,7 +701,6 @@ void fs_proc_sys_dev_boot(void) {
674 errExit("mounting /proc/sys"); 701 errExit("mounting /proc/sys");
675 fs_logger("read-only /proc/sys"); 702 fs_logger("read-only /proc/sys");
676 703
677
678 /* Mount a version of /sys that describes the network namespace */ 704 /* Mount a version of /sys that describes the network namespace */
679 if (arg_debug) 705 if (arg_debug)
680 printf("Remounting /sys directory\n"); 706 printf("Remounting /sys directory\n");
@@ -689,13 +715,13 @@ void fs_proc_sys_dev_boot(void) {
689 else 715 else
690 fs_logger("remount /sys"); 716 fs_logger("remount /sys");
691 717
718 EUID_USER();
719
692 disable_file(BLACKLIST_FILE, "/sys/firmware"); 720 disable_file(BLACKLIST_FILE, "/sys/firmware");
693 disable_file(BLACKLIST_FILE, "/sys/hypervisor"); 721 disable_file(BLACKLIST_FILE, "/sys/hypervisor");
694 { // 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
695 EUID_USER();
696 profile_add("blacklist /sys/fs"); 723 profile_add("blacklist /sys/fs");
697 profile_add("blacklist /sys/module"); 724 profile_add("blacklist /sys/module");
698 EUID_ROOT();
699 } 725 }
700 disable_file(BLACKLIST_FILE, "/sys/power"); 726 disable_file(BLACKLIST_FILE, "/sys/power");
701 disable_file(BLACKLIST_FILE, "/sys/kernel/debug"); 727 disable_file(BLACKLIST_FILE, "/sys/kernel/debug");
@@ -739,12 +765,8 @@ void fs_proc_sys_dev_boot(void) {
739 // disable /dev/port 765 // disable /dev/port
740 disable_file(BLACKLIST_FILE, "/dev/port"); 766 disable_file(BLACKLIST_FILE, "/dev/port");
741 767
742
743
744 // disable various ipc sockets in /run/user 768 // disable various ipc sockets in /run/user
745 if (!arg_writable_run_user) { 769 if (!arg_writable_run_user) {
746 struct stat s;
747
748 char *fname; 770 char *fname;
749 if (asprintf(&fname, "/run/user/%d", getuid()) == -1) 771 if (asprintf(&fname, "/run/user/%d", getuid()) == -1)
750 errExit("asprintf"); 772 errExit("asprintf");
@@ -755,8 +777,7 @@ void fs_proc_sys_dev_boot(void) {
755 errExit("asprintf"); 777 errExit("asprintf");
756 if (create_empty_dir_as_user(fnamegpg, 0700)) 778 if (create_empty_dir_as_user(fnamegpg, 0700))
757 fs_logger2("create", fnamegpg); 779 fs_logger2("create", fnamegpg);
758 if (stat(fnamegpg, &s) == 0) 780 disable_file(BLACKLIST_FILE, fnamegpg);
759 disable_file(BLACKLIST_FILE, fnamegpg);
760 free(fnamegpg); 781 free(fnamegpg);
761 782
762 // disable /run/user/{uid}/systemd 783 // disable /run/user/{uid}/systemd
@@ -765,8 +786,7 @@ void fs_proc_sys_dev_boot(void) {
765 errExit("asprintf"); 786 errExit("asprintf");
766 if (create_empty_dir_as_user(fnamesysd, 0755)) 787 if (create_empty_dir_as_user(fnamesysd, 0755))
767 fs_logger2("create", fnamesysd); 788 fs_logger2("create", fnamesysd);
768 if (stat(fnamesysd, &s) == 0) 789 disable_file(BLACKLIST_FILE, fnamesysd);
769 disable_file(BLACKLIST_FILE, fnamesysd);
770 free(fnamesysd); 790 free(fnamesysd);
771 } 791 }
772 free(fname); 792 free(fname);
@@ -777,30 +797,26 @@ void fs_proc_sys_dev_boot(void) {
777 disable_file(BLACKLIST_FILE, "/dev/kmsg"); 797 disable_file(BLACKLIST_FILE, "/dev/kmsg");
778 disable_file(BLACKLIST_FILE, "/proc/kmsg"); 798 disable_file(BLACKLIST_FILE, "/proc/kmsg");
779 } 799 }
800
801 EUID_ROOT();
780} 802}
781 803
782// disable firejail configuration in ~/.config/firejail 804// disable firejail configuration in ~/.config/firejail
783void disable_config(void) { 805void disable_config(void) {
784 struct stat s; 806 EUID_USER();
785
786 char *fname; 807 char *fname;
787 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1) 808 if (asprintf(&fname, "%s/.config/firejail", cfg.homedir) == -1)
788 errExit("asprintf"); 809 errExit("asprintf");
789 if (stat(fname, &s) == 0) 810 disable_file(BLACKLIST_FILE, fname);
790 disable_file(BLACKLIST_FILE, fname);
791 free(fname); 811 free(fname);
792 812
793 // disable run time information 813 // disable run time information
794 if (stat(RUN_FIREJAIL_NETWORK_DIR, &s) == 0) 814 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR);
795 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR); 815 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_BANDWIDTH_DIR);
796 if (stat(RUN_FIREJAIL_BANDWIDTH_DIR, &s) == 0) 816 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR);
797 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_BANDWIDTH_DIR); 817 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
798 if (stat(RUN_FIREJAIL_NAME_DIR, &s) == 0) 818 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
799 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NAME_DIR); 819 EUID_ROOT();
800 if (stat(RUN_FIREJAIL_PROFILE_DIR, &s) == 0)
801 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
802 if (stat(RUN_FIREJAIL_X11_DIR, &s) == 0)
803 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
804} 820}
805 821
806 822
@@ -862,6 +878,7 @@ void fs_basic_fs(void) {
862#ifdef HAVE_OVERLAYFS 878#ifdef HAVE_OVERLAYFS
863char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { 879char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
864 assert(subdirname); 880 assert(subdirname);
881 EUID_ASSERT();
865 struct stat s; 882 struct stat s;
866 char *dirname; 883 char *dirname;
867 884
@@ -1221,6 +1238,7 @@ void fs_overlayfs(void) {
1221 1238
1222// this function is called from sandbox.c before blacklist/whitelist functions 1239// this function is called from sandbox.c before blacklist/whitelist functions
1223void fs_private_tmp(void) { 1240void fs_private_tmp(void) {
1241 EUID_ASSERT();
1224 if (arg_debug) 1242 if (arg_debug)
1225 printf("Generate private-tmp whitelist commands\n"); 1243 printf("Generate private-tmp whitelist commands\n");
1226 1244
@@ -1241,8 +1259,8 @@ void fs_private_tmp(void) {
1241 1259
1242 // whitelist x11 directory 1260 // whitelist x11 directory
1243 profile_add("whitelist /tmp/.X11-unix"); 1261 profile_add("whitelist /tmp/.X11-unix");
1244 // read-only x11 directory 1262 // read-only x11 directory
1245 profile_add("read-only /tmp/.X11-unix"); 1263 profile_add("read-only /tmp/.X11-unix");
1246 1264
1247 // whitelist any pulse* file in /tmp directory 1265 // whitelist any pulse* file in /tmp directory
1248 // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user 1266 // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user