diff options
Diffstat (limited to 'src/firejail/fs.c')
-rw-r--r-- | src/firejail/fs.c | 150 |
1 files changed, 75 insertions, 75 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index ac68e7738..c60322dda 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -55,7 +55,7 @@ static void disable_file(OPERATION op, const char *filename) { | |||
55 | assert(filename); | 55 | assert(filename); |
56 | assert(op <OPERATION_MAX); | 56 | assert(op <OPERATION_MAX); |
57 | last_disable = UNSUCCESSFUL; | 57 | last_disable = UNSUCCESSFUL; |
58 | 58 | ||
59 | // Resolve all symlinks | 59 | // Resolve all symlinks |
60 | char* fname = realpath(filename, NULL); | 60 | char* fname = realpath(filename, NULL); |
61 | if (fname == NULL && errno != EACCES) { | 61 | if (fname == NULL && errno != EACCES) { |
@@ -87,10 +87,10 @@ static void disable_file(OPERATION op, const char *filename) { | |||
87 | if (arg_debug) | 87 | if (arg_debug) |
88 | printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename); | 88 | printf("Warning (blacklisting): %s is an invalid file, skipping...\n", filename); |
89 | } | 89 | } |
90 | 90 | ||
91 | return; | 91 | return; |
92 | } | 92 | } |
93 | 93 | ||
94 | // if the file is not present, do nothing | 94 | // if the file is not present, do nothing |
95 | struct stat s; | 95 | struct stat s; |
96 | if (fname == NULL) | 96 | if (fname == NULL) |
@@ -124,7 +124,7 @@ static void disable_file(OPERATION op, const char *filename) { | |||
124 | else | 124 | else |
125 | printf(" - no logging\n"); | 125 | printf(" - no logging\n"); |
126 | } | 126 | } |
127 | 127 | ||
128 | if (S_ISDIR(s.st_mode)) { | 128 | if (S_ISDIR(s.st_mode)) { |
129 | if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) | 129 | if (mount(RUN_RO_DIR, fname, "none", MS_BIND, "mode=400,gid=0") < 0) |
130 | errExit("disable file"); | 130 | errExit("disable file"); |
@@ -243,7 +243,7 @@ void fs_blacklist(void) { | |||
243 | ProfileEntry *entry = cfg.profile; | 243 | ProfileEntry *entry = cfg.profile; |
244 | if (!entry) | 244 | if (!entry) |
245 | return; | 245 | return; |
246 | 246 | ||
247 | size_t noblacklist_c = 0; | 247 | size_t noblacklist_c = 0; |
248 | size_t noblacklist_m = 32; | 248 | size_t noblacklist_m = 32; |
249 | char **noblacklist = calloc(noblacklist_m, sizeof(*noblacklist)); | 249 | char **noblacklist = calloc(noblacklist_m, sizeof(*noblacklist)); |
@@ -256,7 +256,7 @@ void fs_blacklist(void) { | |||
256 | char *ptr; | 256 | char *ptr; |
257 | 257 | ||
258 | // whitelist commands handled by fs_whitelist() | 258 | // whitelist commands handled by fs_whitelist() |
259 | if (strncmp(entry->data, "whitelist ", 10) == 0 || | 259 | if (strncmp(entry->data, "whitelist ", 10) == 0 || |
260 | strncmp(entry->data, "nowhitelist ", 12) == 0 || | 260 | strncmp(entry->data, "nowhitelist ", 12) == 0 || |
261 | *entry->data == '\0') { | 261 | *entry->data == '\0') { |
262 | entry = entry->next; | 262 | entry = entry->next; |
@@ -275,7 +275,7 @@ void fs_blacklist(void) { | |||
275 | entry = entry->next; | 275 | entry = entry->next; |
276 | continue; | 276 | continue; |
277 | } | 277 | } |
278 | 278 | ||
279 | // mount --bind olddir newdir | 279 | // mount --bind olddir newdir |
280 | if (arg_debug) | 280 | if (arg_debug) |
281 | printf("Mount-bind %s on top of %s\n", dname1, dname2); | 281 | printf("Mount-bind %s on top of %s\n", dname1, dname2); |
@@ -284,8 +284,8 @@ void fs_blacklist(void) { | |||
284 | errExit("mount bind"); | 284 | errExit("mount bind"); |
285 | /* coverity[toctou] */ | 285 | /* coverity[toctou] */ |
286 | if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode)) | 286 | if (set_perms(dname2, s.st_uid, s.st_gid,s.st_mode)) |
287 | errExit("set_perms"); | 287 | errExit("set_perms"); |
288 | 288 | ||
289 | entry = entry->next; | 289 | entry = entry->next; |
290 | continue; | 290 | continue; |
291 | } | 291 | } |
@@ -348,33 +348,33 @@ void fs_blacklist(void) { | |||
348 | else if (strncmp(entry->data, "read-only ", 10) == 0) { | 348 | else if (strncmp(entry->data, "read-only ", 10) == 0) { |
349 | ptr = entry->data + 10; | 349 | ptr = entry->data + 10; |
350 | op = MOUNT_READONLY; | 350 | op = MOUNT_READONLY; |
351 | } | 351 | } |
352 | else if (strncmp(entry->data, "read-write ", 11) == 0) { | 352 | else if (strncmp(entry->data, "read-write ", 11) == 0) { |
353 | ptr = entry->data + 11; | 353 | ptr = entry->data + 11; |
354 | op = MOUNT_RDWR; | 354 | op = MOUNT_RDWR; |
355 | } | 355 | } |
356 | else if (strncmp(entry->data, "noexec ", 7) == 0) { | 356 | else if (strncmp(entry->data, "noexec ", 7) == 0) { |
357 | ptr = entry->data + 7; | 357 | ptr = entry->data + 7; |
358 | op = MOUNT_NOEXEC; | 358 | op = MOUNT_NOEXEC; |
359 | } | 359 | } |
360 | else if (strncmp(entry->data, "tmpfs ", 6) == 0) { | 360 | else if (strncmp(entry->data, "tmpfs ", 6) == 0) { |
361 | ptr = entry->data + 6; | 361 | ptr = entry->data + 6; |
362 | op = MOUNT_TMPFS; | 362 | op = MOUNT_TMPFS; |
363 | } | 363 | } |
364 | else if (strncmp(entry->data, "mkdir ", 6) == 0) { | 364 | else if (strncmp(entry->data, "mkdir ", 6) == 0) { |
365 | EUID_USER(); | 365 | EUID_USER(); |
366 | fs_mkdir(entry->data + 6); | 366 | fs_mkdir(entry->data + 6); |
367 | EUID_ROOT(); | 367 | EUID_ROOT(); |
368 | entry = entry->next; | 368 | entry = entry->next; |
369 | continue; | 369 | continue; |
370 | } | 370 | } |
371 | else if (strncmp(entry->data, "mkfile ", 7) == 0) { | 371 | else if (strncmp(entry->data, "mkfile ", 7) == 0) { |
372 | EUID_USER(); | 372 | EUID_USER(); |
373 | fs_mkfile(entry->data + 7); | 373 | fs_mkfile(entry->data + 7); |
374 | EUID_ROOT(); | 374 | EUID_ROOT(); |
375 | entry = entry->next; | 375 | entry = entry->next; |
376 | continue; | 376 | continue; |
377 | } | 377 | } |
378 | else { | 378 | else { |
379 | fprintf(stderr, "Error: invalid profile line %s\n", entry->data); | 379 | fprintf(stderr, "Error: invalid profile line %s\n", entry->data); |
380 | entry = entry->next; | 380 | entry = entry->next; |
@@ -446,10 +446,10 @@ static void fs_rdwr(const char *dir) { | |||
446 | fwarning("you are not allowed to change %s to read-write\n", dir); | 446 | fwarning("you are not allowed to change %s to read-write\n", dir); |
447 | return; | 447 | return; |
448 | } | 448 | } |
449 | 449 | ||
450 | // mount --bind /bin /bin | 450 | // mount --bind /bin /bin |
451 | // mount --bind -o remount,rw /bin | 451 | // mount --bind -o remount,rw /bin |
452 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 452 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
453 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | 453 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) |
454 | errExit("mount read-write"); | 454 | errExit("mount read-write"); |
455 | fs_logger2("read-write", dir); | 455 | fs_logger2("read-write", dir); |
@@ -464,7 +464,7 @@ void fs_noexec(const char *dir) { | |||
464 | if (rv == 0) { | 464 | if (rv == 0) { |
465 | // mount --bind /bin /bin | 465 | // mount --bind /bin /bin |
466 | // mount --bind -o remount,ro /bin | 466 | // mount --bind -o remount,ro /bin |
467 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 467 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
468 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) | 468 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) |
469 | errExit("mount noexec"); | 469 | errExit("mount noexec"); |
470 | fs_logger2("noexec", dir); | 470 | fs_logger2("noexec", dir); |
@@ -504,11 +504,11 @@ void fs_proc_sys_dev_boot(void) { | |||
504 | fwarning("failed to mount /sys\n"); | 504 | fwarning("failed to mount /sys\n"); |
505 | else | 505 | else |
506 | fs_logger("remount /sys"); | 506 | fs_logger("remount /sys"); |
507 | 507 | ||
508 | disable_file(BLACKLIST_FILE, "/sys/firmware"); | 508 | disable_file(BLACKLIST_FILE, "/sys/firmware"); |
509 | disable_file(BLACKLIST_FILE, "/sys/hypervisor"); | 509 | disable_file(BLACKLIST_FILE, "/sys/hypervisor"); |
510 | { // allow user access to /sys/fs if "--noblacklist=/sys/fs" is present on the command line | 510 | { // allow user access to /sys/fs if "--noblacklist=/sys/fs" is present on the command line |
511 | EUID_USER(); | 511 | EUID_USER(); |
512 | profile_add("blacklist /sys/fs"); | 512 | profile_add("blacklist /sys/fs"); |
513 | EUID_ROOT(); | 513 | EUID_ROOT(); |
514 | } | 514 | } |
@@ -519,11 +519,11 @@ void fs_proc_sys_dev_boot(void) { | |||
519 | disable_file(BLACKLIST_FILE, "/sys/kernel/uevent_helper"); | 519 | disable_file(BLACKLIST_FILE, "/sys/kernel/uevent_helper"); |
520 | 520 | ||
521 | // various /proc/sys files | 521 | // various /proc/sys files |
522 | disable_file(BLACKLIST_FILE, "/proc/sys/security"); | 522 | disable_file(BLACKLIST_FILE, "/proc/sys/security"); |
523 | disable_file(BLACKLIST_FILE, "/proc/sys/efi/vars"); | 523 | disable_file(BLACKLIST_FILE, "/proc/sys/efi/vars"); |
524 | disable_file(BLACKLIST_FILE, "/proc/sys/fs/binfmt_misc"); | 524 | disable_file(BLACKLIST_FILE, "/proc/sys/fs/binfmt_misc"); |
525 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/core_pattern"); | 525 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/core_pattern"); |
526 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/modprobe"); | 526 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/modprobe"); |
527 | disable_file(BLACKLIST_FILE, "/proc/sysrq-trigger"); | 527 | disable_file(BLACKLIST_FILE, "/proc/sysrq-trigger"); |
528 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/hotplug"); | 528 | disable_file(BLACKLIST_FILE, "/proc/sys/kernel/hotplug"); |
529 | disable_file(BLACKLIST_FILE, "/proc/sys/vm/panic_on_oom"); | 529 | disable_file(BLACKLIST_FILE, "/proc/sys/vm/panic_on_oom"); |
@@ -531,15 +531,15 @@ void fs_proc_sys_dev_boot(void) { | |||
531 | // various /proc files | 531 | // various /proc files |
532 | disable_file(BLACKLIST_FILE, "/proc/irq"); | 532 | disable_file(BLACKLIST_FILE, "/proc/irq"); |
533 | disable_file(BLACKLIST_FILE, "/proc/bus"); | 533 | disable_file(BLACKLIST_FILE, "/proc/bus"); |
534 | disable_file(BLACKLIST_FILE, "/proc/config.gz"); | 534 | disable_file(BLACKLIST_FILE, "/proc/config.gz"); |
535 | disable_file(BLACKLIST_FILE, "/proc/sched_debug"); | 535 | disable_file(BLACKLIST_FILE, "/proc/sched_debug"); |
536 | disable_file(BLACKLIST_FILE, "/proc/timer_list"); | 536 | disable_file(BLACKLIST_FILE, "/proc/timer_list"); |
537 | disable_file(BLACKLIST_FILE, "/proc/timer_stats"); | 537 | disable_file(BLACKLIST_FILE, "/proc/timer_stats"); |
538 | disable_file(BLACKLIST_FILE, "/proc/kcore"); | 538 | disable_file(BLACKLIST_FILE, "/proc/kcore"); |
539 | disable_file(BLACKLIST_FILE, "/proc/kallsyms"); | 539 | disable_file(BLACKLIST_FILE, "/proc/kallsyms"); |
540 | disable_file(BLACKLIST_FILE, "/proc/mem"); | 540 | disable_file(BLACKLIST_FILE, "/proc/mem"); |
541 | disable_file(BLACKLIST_FILE, "/proc/kmem"); | 541 | disable_file(BLACKLIST_FILE, "/proc/kmem"); |
542 | 542 | ||
543 | // remove kernel symbol information | 543 | // remove kernel symbol information |
544 | if (!arg_allow_debuggers) { | 544 | if (!arg_allow_debuggers) { |
545 | disable_file(BLACKLIST_FILE, "/usr/src/linux"); | 545 | disable_file(BLACKLIST_FILE, "/usr/src/linux"); |
@@ -547,18 +547,18 @@ void fs_proc_sys_dev_boot(void) { | |||
547 | disable_file(BLACKLIST_FILE, "/usr/lib/debug"); | 547 | disable_file(BLACKLIST_FILE, "/usr/lib/debug"); |
548 | disable_file(BLACKLIST_FILE, "/boot"); | 548 | disable_file(BLACKLIST_FILE, "/boot"); |
549 | } | 549 | } |
550 | 550 | ||
551 | // disable /selinux | 551 | // disable /selinux |
552 | disable_file(BLACKLIST_FILE, "/selinux"); | 552 | disable_file(BLACKLIST_FILE, "/selinux"); |
553 | 553 | ||
554 | // disable /dev/port | 554 | // disable /dev/port |
555 | disable_file(BLACKLIST_FILE, "/dev/port"); | 555 | disable_file(BLACKLIST_FILE, "/dev/port"); |
556 | 556 | ||
557 | 557 | ||
558 | 558 | ||
559 | // disable various ipc sockets in /run/user | 559 | // disable various ipc sockets in /run/user |
560 | struct stat s; | 560 | struct stat s; |
561 | 561 | ||
562 | char *fname; | 562 | char *fname; |
563 | if (asprintf(&fname, "/run/usr/%d", getuid()) == -1) | 563 | if (asprintf(&fname, "/run/usr/%d", getuid()) == -1) |
564 | errExit("asprintf"); | 564 | errExit("asprintf"); |
@@ -567,24 +567,24 @@ void fs_proc_sys_dev_boot(void) { | |||
567 | char *fnamegpg; | 567 | char *fnamegpg; |
568 | if (asprintf(&fnamegpg, "/run/user/%d/gnupg", getuid()) == -1) | 568 | if (asprintf(&fnamegpg, "/run/user/%d/gnupg", getuid()) == -1) |
569 | errExit("asprintf"); | 569 | errExit("asprintf"); |
570 | if (stat(fnamegpg, &s) == -1) | 570 | if (stat(fnamegpg, &s) == -1) |
571 | mkdir_attr(fnamegpg, 0700, getuid(), getgid()); | 571 | mkdir_attr(fnamegpg, 0700, getuid(), getgid()); |
572 | if (stat(fnamegpg, &s) == 0) | 572 | if (stat(fnamegpg, &s) == 0) |
573 | disable_file(BLACKLIST_FILE, fnamegpg); | 573 | disable_file(BLACKLIST_FILE, fnamegpg); |
574 | free(fnamegpg); | 574 | free(fnamegpg); |
575 | 575 | ||
576 | // disable /run/user/{uid}/systemd | 576 | // disable /run/user/{uid}/systemd |
577 | char *fnamesysd; | 577 | char *fnamesysd; |
578 | if (asprintf(&fnamesysd, "/run/user/%d/systemd", getuid()) == -1) | 578 | if (asprintf(&fnamesysd, "/run/user/%d/systemd", getuid()) == -1) |
579 | errExit("asprintf"); | 579 | errExit("asprintf"); |
580 | if (stat(fnamesysd, &s) == -1) | 580 | if (stat(fnamesysd, &s) == -1) |
581 | mkdir_attr(fnamesysd, 0755, getuid(), getgid()); | 581 | mkdir_attr(fnamesysd, 0755, getuid(), getgid()); |
582 | if (stat(fnamesysd, &s) == 0) | 582 | if (stat(fnamesysd, &s) == 0) |
583 | disable_file(BLACKLIST_FILE, fnamesysd); | 583 | disable_file(BLACKLIST_FILE, fnamesysd); |
584 | free(fnamesysd); | 584 | free(fnamesysd); |
585 | } | 585 | } |
586 | free(fname); | 586 | free(fname); |
587 | 587 | ||
588 | if (getuid() != 0) { | 588 | if (getuid() != 0) { |
589 | // disable /dev/kmsg and /proc/kmsg | 589 | // disable /dev/kmsg and /proc/kmsg |
590 | disable_file(BLACKLIST_FILE, "/dev/kmsg"); | 590 | disable_file(BLACKLIST_FILE, "/dev/kmsg"); |
@@ -602,7 +602,7 @@ static void disable_config(void) { | |||
602 | if (stat(fname, &s) == 0) | 602 | if (stat(fname, &s) == 0) |
603 | disable_file(BLACKLIST_FILE, fname); | 603 | disable_file(BLACKLIST_FILE, fname); |
604 | free(fname); | 604 | free(fname); |
605 | 605 | ||
606 | // disable run time information | 606 | // disable run time information |
607 | if (stat(RUN_FIREJAIL_NETWORK_DIR, &s) == 0) | 607 | if (stat(RUN_FIREJAIL_NETWORK_DIR, &s) == 0) |
608 | disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR); | 608 | disable_file(BLACKLIST_FILE, RUN_FIREJAIL_NETWORK_DIR); |
@@ -618,7 +618,7 @@ static void disable_config(void) { | |||
618 | // build a basic read-only filesystem | 618 | // build a basic read-only filesystem |
619 | void fs_basic_fs(void) { | 619 | void fs_basic_fs(void) { |
620 | uid_t uid = getuid(); | 620 | uid_t uid = getuid(); |
621 | 621 | ||
622 | if (arg_debug) | 622 | if (arg_debug) |
623 | printf("Mounting read-only /bin, /sbin, /lib, /lib32, /lib64, /usr"); | 623 | printf("Mounting read-only /bin, /sbin, /lib, /lib32, /lib64, /usr"); |
624 | if (!arg_writable_etc) { | 624 | if (!arg_writable_etc) { |
@@ -649,15 +649,15 @@ void fs_basic_fs(void) { | |||
649 | fs_var_log(); | 649 | fs_var_log(); |
650 | else | 650 | else |
651 | fs_rdwr("/var/log"); | 651 | fs_rdwr("/var/log"); |
652 | 652 | ||
653 | fs_var_lib(); | 653 | fs_var_lib(); |
654 | fs_var_cache(); | 654 | fs_var_cache(); |
655 | fs_var_utmp(); | 655 | fs_var_utmp(); |
656 | fs_machineid(); | 656 | fs_machineid(); |
657 | 657 | ||
658 | // don't leak user information | 658 | // don't leak user information |
659 | restrict_users(); | 659 | restrict_users(); |
660 | 660 | ||
661 | // when starting as root, firejail config is not disabled; | 661 | // when starting as root, firejail config is not disabled; |
662 | // this mode could be used to install and test new software by chaining | 662 | // this mode could be used to install and test new software by chaining |
663 | // firejail sandboxes (firejail --force) | 663 | // firejail sandboxes (firejail --force) |
@@ -675,7 +675,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { | |||
675 | // create ~/.firejail directory | 675 | // create ~/.firejail directory |
676 | if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) | 676 | if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) |
677 | errExit("asprintf"); | 677 | errExit("asprintf"); |
678 | 678 | ||
679 | if (is_link(dirname)) { | 679 | if (is_link(dirname)) { |
680 | fprintf(stderr, "Error: invalid ~/.firejail directory\n"); | 680 | fprintf(stderr, "Error: invalid ~/.firejail directory\n"); |
681 | exit(1); | 681 | exit(1); |
@@ -688,7 +688,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) { | |||
688 | if (child == 0) { | 688 | if (child == 0) { |
689 | // drop privileges | 689 | // drop privileges |
690 | drop_privs(0); | 690 | drop_privs(0); |
691 | 691 | ||
692 | // create directory | 692 | // create directory |
693 | if (mkdir(dirname, 0700)) | 693 | if (mkdir(dirname, 0700)) |
694 | errExit("mkdir"); | 694 | errExit("mkdir"); |
@@ -770,7 +770,7 @@ void fs_overlayfs(void) { | |||
770 | fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version); | 770 | fprintf(stderr, "Error: cannot extract Linux kernel version: %s\n", u.version); |
771 | exit(1); | 771 | exit(1); |
772 | } | 772 | } |
773 | 773 | ||
774 | if (arg_debug) | 774 | if (arg_debug) |
775 | printf("Linux kernel version %d.%d\n", major, minor); | 775 | printf("Linux kernel version %d.%d\n", major, minor); |
776 | int oldkernel = 0; | 776 | int oldkernel = 0; |
@@ -780,7 +780,7 @@ void fs_overlayfs(void) { | |||
780 | } | 780 | } |
781 | if (major == 3 && minor < 18) | 781 | if (major == 3 && minor < 18) |
782 | oldkernel = 1; | 782 | oldkernel = 1; |
783 | 783 | ||
784 | char *oroot; | 784 | char *oroot; |
785 | if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) | 785 | if(asprintf(&oroot, "%s/oroot", RUN_MNT_DIR) == -1) |
786 | errExit("asprintf"); | 786 | errExit("asprintf"); |
@@ -818,7 +818,7 @@ void fs_overlayfs(void) { | |||
818 | } | 818 | } |
819 | else if (set_perms(odiff, 0, 0, 0755)) | 819 | else if (set_perms(odiff, 0, 0, 0755)) |
820 | errExit("set_perms"); | 820 | errExit("set_perms"); |
821 | 821 | ||
822 | char *owork; | 822 | char *owork; |
823 | if(asprintf(&owork, "%s/owork", basedir) == -1) | 823 | if(asprintf(&owork, "%s/owork", basedir) == -1) |
824 | errExit("asprintf"); | 824 | errExit("asprintf"); |
@@ -829,7 +829,7 @@ void fs_overlayfs(void) { | |||
829 | } | 829 | } |
830 | else if (set_perms(owork, 0, 0, 0755)) | 830 | else if (set_perms(owork, 0, 0, 0755)) |
831 | errExit("chown"); | 831 | errExit("chown"); |
832 | 832 | ||
833 | // mount overlayfs | 833 | // mount overlayfs |
834 | if (arg_debug) | 834 | if (arg_debug) |
835 | printf("Mounting OverlayFS\n"); | 835 | printf("Mounting OverlayFS\n"); |
@@ -849,11 +849,11 @@ void fs_overlayfs(void) { | |||
849 | errExit("asprintf"); | 849 | errExit("asprintf"); |
850 | if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) | 850 | if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) |
851 | errExit("mounting overlayfs"); | 851 | errExit("mounting overlayfs"); |
852 | 852 | ||
853 | //*************************** | 853 | //*************************** |
854 | // issue #263 start code | 854 | // issue #263 start code |
855 | // My setup has a separate mount point for /home. When the overlay is mounted, | 855 | // My setup has a separate mount point for /home. When the overlay is mounted, |
856 | // the overlay does not contain the original /home contents. | 856 | // the overlay does not contain the original /home contents. |
857 | // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work | 857 | // I added code to create a second overlay for /home if the overlay home dir is empty and this seems to work |
858 | // @dshmgh, Jan 2016 | 858 | // @dshmgh, Jan 2016 |
859 | { | 859 | { |
@@ -862,22 +862,22 @@ void fs_overlayfs(void) { | |||
862 | char *hroot; | 862 | char *hroot; |
863 | char *hdiff; | 863 | char *hdiff; |
864 | char *hwork; | 864 | char *hwork; |
865 | 865 | ||
866 | // dons add debug | 866 | // dons add debug |
867 | if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork); | 867 | if (arg_debug) printf ("DEBUG: chroot dirs are oroot %s odiff %s owork %s\n",oroot,odiff,owork); |
868 | 868 | ||
869 | // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it? | 869 | // BEFORE NEXT, WE NEED TO TEST IF /home has any contents or do we need to mount it? |
870 | // must create var for oroot/cfg.homedir | 870 | // must create var for oroot/cfg.homedir |
871 | if (asprintf(&overlayhome,"%s%s",oroot,cfg.homedir) == -1) | 871 | if (asprintf(&overlayhome,"%s%s",oroot,cfg.homedir) == -1) |
872 | errExit("asprintf"); | 872 | errExit("asprintf"); |
873 | if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n",overlayhome); | 873 | if (arg_debug) printf ("DEBUG: overlayhome var holds ##%s##\n",overlayhome); |
874 | 874 | ||
875 | // if no homedir in overlay -- create another overlay for /home | 875 | // if no homedir in overlay -- create another overlay for /home |
876 | if (stat(overlayhome, &s) == -1) { | 876 | if (stat(overlayhome, &s) == -1) { |
877 | 877 | ||
878 | if(asprintf(&hroot, "%s/oroot/home", RUN_MNT_DIR) == -1) | 878 | if(asprintf(&hroot, "%s/oroot/home", RUN_MNT_DIR) == -1) |
879 | errExit("asprintf"); | 879 | errExit("asprintf"); |
880 | 880 | ||
881 | if(asprintf(&hdiff, "%s/hdiff", basedir) == -1) | 881 | if(asprintf(&hdiff, "%s/hdiff", basedir) == -1) |
882 | errExit("asprintf"); | 882 | errExit("asprintf"); |
883 | 883 | ||
@@ -887,7 +887,7 @@ void fs_overlayfs(void) { | |||
887 | } | 887 | } |
888 | else if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | 888 | else if (set_perms(hdiff, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) |
889 | errExit("set_perms"); | 889 | errExit("set_perms"); |
890 | 890 | ||
891 | if(asprintf(&hwork, "%s/hwork", basedir) == -1) | 891 | if(asprintf(&hwork, "%s/hwork", basedir) == -1) |
892 | errExit("asprintf"); | 892 | errExit("asprintf"); |
893 | 893 | ||
@@ -897,13 +897,13 @@ void fs_overlayfs(void) { | |||
897 | } | 897 | } |
898 | else if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) | 898 | else if (set_perms(hwork, 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) |
899 | errExit("set_perms"); | 899 | errExit("set_perms"); |
900 | 900 | ||
901 | // no homedir in overlay so now mount another overlay for /home | 901 | // no homedir in overlay so now mount another overlay for /home |
902 | if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1) | 902 | if (asprintf(&option, "lowerdir=/home,upperdir=%s,workdir=%s", hdiff, hwork) == -1) |
903 | errExit("asprintf"); | 903 | errExit("asprintf"); |
904 | if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0) | 904 | if (mount("overlay", hroot, "overlay", MS_MGC_VAL, option) < 0) |
905 | errExit("mounting overlayfs for mounted home directory"); | 905 | errExit("mounting overlayfs for mounted home directory"); |
906 | 906 | ||
907 | printf("OverlayFS for /home configured in %s directory\n", basedir); | 907 | printf("OverlayFS for /home configured in %s directory\n", basedir); |
908 | } // stat(overlayhome) | 908 | } // stat(overlayhome) |
909 | free(overlayhome); | 909 | free(overlayhome); |
@@ -913,7 +913,7 @@ void fs_overlayfs(void) { | |||
913 | } | 913 | } |
914 | if (!arg_quiet) | 914 | if (!arg_quiet) |
915 | printf("OverlayFS configured in %s directory\n", basedir); | 915 | printf("OverlayFS configured in %s directory\n", basedir); |
916 | 916 | ||
917 | // mount-bind dev directory | 917 | // mount-bind dev directory |
918 | if (arg_debug) | 918 | if (arg_debug) |
919 | printf("Mounting /dev\n"); | 919 | printf("Mounting /dev\n"); |
@@ -964,7 +964,7 @@ void fs_overlayfs(void) { | |||
964 | fs_var_log(); | 964 | fs_var_log(); |
965 | else | 965 | else |
966 | fs_rdwr("/var/log"); | 966 | fs_rdwr("/var/log"); |
967 | 967 | ||
968 | fs_var_lib(); | 968 | fs_var_lib(); |
969 | fs_var_cache(); | 969 | fs_var_cache(); |
970 | fs_var_utmp(); | 970 | fs_var_utmp(); |
@@ -987,7 +987,7 @@ void fs_overlayfs(void) { | |||
987 | #endif | 987 | #endif |
988 | 988 | ||
989 | 989 | ||
990 | #ifdef HAVE_CHROOT | 990 | #ifdef HAVE_CHROOT |
991 | // return 1 if error | 991 | // return 1 if error |
992 | void fs_check_chroot_dir(const char *rootdir) { | 992 | void fs_check_chroot_dir(const char *rootdir) { |
993 | EUID_ASSERT(); | 993 | EUID_ASSERT(); |
@@ -1035,7 +1035,7 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1035 | exit(1); | 1035 | exit(1); |
1036 | } | 1036 | } |
1037 | free(name); | 1037 | free(name); |
1038 | 1038 | ||
1039 | // check /proc | 1039 | // check /proc |
1040 | if (asprintf(&name, "%s/proc", rootdir) == -1) | 1040 | if (asprintf(&name, "%s/proc", rootdir) == -1) |
1041 | errExit("asprintf"); | 1041 | errExit("asprintf"); |
@@ -1048,7 +1048,7 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1048 | exit(1); | 1048 | exit(1); |
1049 | } | 1049 | } |
1050 | free(name); | 1050 | free(name); |
1051 | 1051 | ||
1052 | // check /tmp | 1052 | // check /tmp |
1053 | if (asprintf(&name, "%s/tmp", rootdir) == -1) | 1053 | if (asprintf(&name, "%s/tmp", rootdir) == -1) |
1054 | errExit("asprintf"); | 1054 | errExit("asprintf"); |
@@ -1110,7 +1110,7 @@ void fs_check_chroot_dir(const char *rootdir) { | |||
1110 | // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf | 1110 | // chroot into an existing directory; mount exiting /dev and update /etc/resolv.conf |
1111 | void fs_chroot(const char *rootdir) { | 1111 | void fs_chroot(const char *rootdir) { |
1112 | assert(rootdir); | 1112 | assert(rootdir); |
1113 | 1113 | ||
1114 | if (checkcfg(CFG_CHROOT_DESKTOP)) { | 1114 | if (checkcfg(CFG_CHROOT_DESKTOP)) { |
1115 | // mount-bind a /dev in rootdir | 1115 | // mount-bind a /dev in rootdir |
1116 | char *newdev; | 1116 | char *newdev; |
@@ -1121,7 +1121,7 @@ void fs_chroot(const char *rootdir) { | |||
1121 | if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0) | 1121 | if (mount("/dev", newdev, NULL, MS_BIND|MS_REC, NULL) < 0) |
1122 | errExit("mounting /dev"); | 1122 | errExit("mounting /dev"); |
1123 | free(newdev); | 1123 | free(newdev); |
1124 | 1124 | ||
1125 | // x11 | 1125 | // x11 |
1126 | if (getenv("FIREJAIL_X11")) { | 1126 | if (getenv("FIREJAIL_X11")) { |
1127 | char *newx11; | 1127 | char *newx11; |
@@ -1133,7 +1133,7 @@ void fs_chroot(const char *rootdir) { | |||
1133 | errExit("mounting /tmp/.X11-unix"); | 1133 | errExit("mounting /tmp/.X11-unix"); |
1134 | free(newx11); | 1134 | free(newx11); |
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | // some older distros don't have a /run directory | 1137 | // some older distros don't have a /run directory |
1138 | // create one by default | 1138 | // create one by default |
1139 | // create /run/firejail directory in chroot | 1139 | // create /run/firejail directory in chroot |
@@ -1150,7 +1150,7 @@ void fs_chroot(const char *rootdir) { | |||
1150 | errExit("asprintf"); | 1150 | errExit("asprintf"); |
1151 | create_empty_dir_as_root(rundir, 0755); | 1151 | create_empty_dir_as_root(rundir, 0755); |
1152 | free(rundir); | 1152 | free(rundir); |
1153 | 1153 | ||
1154 | // create /run/firejail/mnt directory in chroot and mount the current one | 1154 | // create /run/firejail/mnt directory in chroot and mount the current one |
1155 | if (asprintf(&rundir, "%s%s", rootdir, RUN_MNT_DIR) == -1) | 1155 | if (asprintf(&rundir, "%s%s", rootdir, RUN_MNT_DIR) == -1) |
1156 | errExit("asprintf"); | 1156 | errExit("asprintf"); |
@@ -1173,7 +1173,7 @@ void fs_chroot(const char *rootdir) { | |||
1173 | if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed | 1173 | if (copy_file("/etc/resolv.conf", fname, 0, 0, 0644) == -1) // root needed |
1174 | fwarning("/etc/resolv.conf not initialized\n"); | 1174 | fwarning("/etc/resolv.conf not initialized\n"); |
1175 | } | 1175 | } |
1176 | 1176 | ||
1177 | // chroot into the new directory | 1177 | // chroot into the new directory |
1178 | #ifdef HAVE_GCOV | 1178 | #ifdef HAVE_GCOV |
1179 | __gcov_flush(); | 1179 | __gcov_flush(); |
@@ -1196,15 +1196,15 @@ void fs_chroot(const char *rootdir) { | |||
1196 | fs_var_log(); | 1196 | fs_var_log(); |
1197 | else | 1197 | else |
1198 | fs_rdwr("/var/log"); | 1198 | fs_rdwr("/var/log"); |
1199 | 1199 | ||
1200 | fs_var_lib(); | 1200 | fs_var_lib(); |
1201 | fs_var_cache(); | 1201 | fs_var_cache(); |
1202 | fs_var_utmp(); | 1202 | fs_var_utmp(); |
1203 | fs_machineid(); | 1203 | fs_machineid(); |
1204 | 1204 | ||
1205 | // don't leak user information | 1205 | // don't leak user information |
1206 | restrict_users(); | 1206 | restrict_users(); |
1207 | 1207 | ||
1208 | // when starting as root, firejail config is not disabled; | 1208 | // when starting as root, firejail config is not disabled; |
1209 | // this mode could be used to install and test new software by chaining | 1209 | // this mode could be used to install and test new software by chaining |
1210 | // firejail sandboxes (firejail --force) | 1210 | // firejail sandboxes (firejail --force) |
@@ -1229,10 +1229,10 @@ void fs_private_tmp(void) { | |||
1229 | if (rp) | 1229 | if (rp) |
1230 | free(rp); | 1230 | free(rp); |
1231 | } | 1231 | } |
1232 | 1232 | ||
1233 | // whitelist x11 directory | 1233 | // whitelist x11 directory |
1234 | profile_add("whitelist /tmp/.X11-unix"); | 1234 | profile_add("whitelist /tmp/.X11-unix"); |
1235 | 1235 | ||
1236 | // whitelist any pulse* file in /tmp directory | 1236 | // whitelist any pulse* file in /tmp directory |
1237 | // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user | 1237 | // some distros use PulseAudio sockets under /tmp instead of the socket in /urn/user |
1238 | DIR *dir; | 1238 | DIR *dir; |