aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2018-01-31 09:22:36 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2018-01-31 09:22:36 -0500
commit00b6315c91893c3316686fa9d71350690d506b56 (patch)
tree86a431ef4ca848240ff42ad4c4ec871b4a579516 /src
parentfix cd/dvd for dragon (diff)
downloadfirejail-00b6315c91893c3316686fa9d71350690d506b56.tar.gz
firejail-00b6315c91893c3316686fa9d71350690d506b56.tar.zst
firejail-00b6315c91893c3316686fa9d71350690d506b56.zip
overlay fixes and additional hardening
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs.c5
-rw-r--r--src/firejail/main.c27
-rw-r--r--src/firejail/profile.c12
-rw-r--r--src/firejail/util.c46
5 files changed, 73 insertions, 19 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 97e740e6b..e8dc390d4 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -513,7 +513,7 @@ const char *gnu_basename(const char *path);
513uid_t pid_get_uid(pid_t pid); 513uid_t pid_get_uid(pid_t pid);
514void invalid_filename(const char *fname, int globbing); 514void invalid_filename(const char *fname, int globbing);
515uid_t get_group_id(const char *group); 515uid_t get_group_id(const char *group);
516int remove_directory(const char *path); 516int remove_overlay_directory(void);
517void flush_stdin(void); 517void flush_stdin(void);
518void create_empty_dir_as_root(const char *dir, mode_t mode); 518void create_empty_dir_as_root(const char *dir, mode_t mode);
519void create_empty_file_as_root(const char *dir, mode_t mode); 519void create_empty_file_as_root(const char *dir, mode_t mode);
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index ab2958593..25b52f5ce 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -725,7 +725,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
725 errExit("asprintf"); 725 errExit("asprintf");
726 726
727 if (is_link(dirname)) { 727 if (is_link(dirname)) {
728 fprintf(stderr, "Error: invalid ~/.firejail directory\n"); 728 fprintf(stderr, "Error: ~/.firejail directory is a symbolic link\n");
729 exit(1); 729 exit(1);
730 } 730 }
731 if (stat(dirname, &s) == -1) { 731 if (stat(dirname, &s) == -1) {
@@ -753,7 +753,7 @@ char *fs_check_overlay_dir(const char *subdirname, int allow_reuse) {
753 } 753 }
754 } 754 }
755 else if (s.st_uid != getuid()) { 755 else if (s.st_uid != getuid()) {
756 fprintf(stderr, "Error: invalid ~/.firejail directory\n"); 756 fprintf(stderr, "Error: ~/.firejail directory is not owned by the current user\n");
757 exit(1); 757 exit(1);
758 } 758 }
759 free(dirname); 759 free(dirname);
@@ -837,6 +837,7 @@ void fs_overlayfs(void) {
837 if (arg_overlay_keep) { 837 if (arg_overlay_keep) {
838 // set base for working and diff directories 838 // set base for working and diff directories
839 basedir = cfg.overlay_dir; 839 basedir = cfg.overlay_dir;
840 assert(basedir);
840 841
841 // does the overlay exist? 842 // does the overlay exist?
842 if (stat(basedir, &s) == 0) { 843 if (stat(basedir, &s) == 0) {
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 00e3729d0..7543c5f4b 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -314,16 +314,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
314#ifdef HAVE_OVERLAYFS 314#ifdef HAVE_OVERLAYFS
315 else if (strcmp(argv[i], "--overlay-clean") == 0) { 315 else if (strcmp(argv[i], "--overlay-clean") == 0) {
316 if (checkcfg(CFG_OVERLAYFS)) { 316 if (checkcfg(CFG_OVERLAYFS)) {
317 char *path; 317 if (remove_overlay_directory()) {
318 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) 318 fprintf(stderr, "Error: cannot remove overlay directory\n");
319 errExit("asprintf"); 319 exit(1);
320 EUID_ROOT(); 320 }
321 if (setreuid(0, 0) < 0 ||
322 setregid(0, 0) < 0)
323 errExit("setreuid/setregid");
324 errno = 0;
325 if (remove_directory(path))
326 errExit("remove_directory");
327 } 321 }
328 else 322 else
329 exit_err_feature("overlayfs"); 323 exit_err_feature("overlayfs");
@@ -1429,6 +1423,11 @@ int main(int argc, char **argv) {
1429#ifdef HAVE_OVERLAYFS 1423#ifdef HAVE_OVERLAYFS
1430 else if (strcmp(argv[i], "--overlay") == 0) { 1424 else if (strcmp(argv[i], "--overlay") == 0) {
1431 if (checkcfg(CFG_OVERLAYFS)) { 1425 if (checkcfg(CFG_OVERLAYFS)) {
1426 if (arg_overlay) {
1427 fprintf(stderr, "Error: only one overlay command is allowed\n");
1428 exit(1);
1429 }
1430
1432 if (cfg.chrootdir) { 1431 if (cfg.chrootdir) {
1433 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 1432 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1434 exit(1); 1433 exit(1);
@@ -1453,6 +1452,10 @@ int main(int argc, char **argv) {
1453 } 1452 }
1454 else if (strncmp(argv[i], "--overlay-named=", 16) == 0) { 1453 else if (strncmp(argv[i], "--overlay-named=", 16) == 0) {
1455 if (checkcfg(CFG_OVERLAYFS)) { 1454 if (checkcfg(CFG_OVERLAYFS)) {
1455 if (arg_overlay) {
1456 fprintf(stderr, "Error: only one overlay command is allowed\n");
1457 exit(1);
1458 }
1456 if (cfg.chrootdir) { 1459 if (cfg.chrootdir) {
1457 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 1460 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1458 exit(1); 1461 exit(1);
@@ -1485,6 +1488,10 @@ int main(int argc, char **argv) {
1485 } 1488 }
1486 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) { 1489 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) {
1487 if (checkcfg(CFG_OVERLAYFS)) { 1490 if (checkcfg(CFG_OVERLAYFS)) {
1491 if (arg_overlay) {
1492 fprintf(stderr, "Error: only one overlay command is allowed\n");
1493 exit(1);
1494 }
1488 if (cfg.chrootdir) { 1495 if (cfg.chrootdir) {
1489 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 1496 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1490 exit(1); 1497 exit(1);
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index d0c43d13e..77308b7ac 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -920,6 +920,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
920#ifdef HAVE_OVERLAYFS 920#ifdef HAVE_OVERLAYFS
921 if (strncmp(ptr, "overlay-named ", 14) == 0) { 921 if (strncmp(ptr, "overlay-named ", 14) == 0) {
922 if (checkcfg(CFG_OVERLAYFS)) { 922 if (checkcfg(CFG_OVERLAYFS)) {
923 if (arg_overlay) {
924 fprintf(stderr, "Error: only one overlay command is allowed\n");
925 exit(1);
926 }
923 if (cfg.chrootdir) { 927 if (cfg.chrootdir) {
924 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 928 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
925 exit(1); 929 exit(1);
@@ -951,6 +955,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
951 return 0; 955 return 0;
952 } else if (strcmp(ptr, "overlay-tmpfs") == 0) { 956 } else if (strcmp(ptr, "overlay-tmpfs") == 0) {
953 if (checkcfg(CFG_OVERLAYFS)) { 957 if (checkcfg(CFG_OVERLAYFS)) {
958 if (arg_overlay) {
959 fprintf(stderr, "Error: only one overlay command is allowed\n");
960 exit(1);
961 }
954 if (cfg.chrootdir) { 962 if (cfg.chrootdir) {
955 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 963 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
956 exit(1); 964 exit(1);
@@ -966,6 +974,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
966 } 974 }
967 } else if (strcmp(ptr, "overlay") == 0) { 975 } else if (strcmp(ptr, "overlay") == 0) {
968 if (checkcfg(CFG_OVERLAYFS)) { 976 if (checkcfg(CFG_OVERLAYFS)) {
977 if (arg_overlay) {
978 fprintf(stderr, "Error: only one overlay command is allowed\n");
979 exit(1);
980 }
969 if (cfg.chrootdir) { 981 if (cfg.chrootdir) {
970 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); 982 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
971 exit(1); 983 exit(1);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 5a9f3a6e0..0adca5e33 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -800,21 +800,55 @@ uid_t get_group_id(const char *group) {
800 return gid; 800 return gid;
801} 801}
802 802
803 803static int len_homedir = 0;
804static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { 804static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
805 (void) sb; 805 (void) sb;
806 (void) typeflag; 806 (void) typeflag;
807 (void) ftwbuf; 807 (void) ftwbuf;
808 assert(fpath);
808 809
809 int rv = remove(fpath); 810 if (len_homedir == 0)
810 if (rv) 811 len_homedir = strlen(cfg.homedir);
811 perror(fpath);
812 812
813 return rv; 813 char *rp = realpath(fpath, NULL); // this should never fail!
814 if (!rp)
815 return 1;
816 if (strncmp(rp, cfg.homedir, len_homedir) != 0)
817 return 1;
818 free(rp);
819
820 if (remove(fpath)) { // removes the link not the actual file
821 fprintf(stderr, "Error: cannot remove file %s\n", fpath);
822 exit(1);
823 }
824
825 return 0;
814} 826}
815 827
816 828
817int remove_directory(const char *path) { 829int remove_overlay_directory(void) {
830 sleep(1);
831
832 char *path;
833 if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1)
834 errExit("asprintf");
835
836 // deal with obvious problems such as symlinks and root ownership
837 if (is_link(path)) {
838 fprintf(stderr, "Error: cannot follow symbolic link\n");
839 exit(1);
840 }
841 if (access(path, R_OK | W_OK | X_OK) == -1) {
842 fprintf(stderr, "Error: cannot access ~/.firejail directory\n");
843 exit(1);
844 }
845
846 EUID_ROOT();
847 if (setreuid(0, 0) < 0 ||
848 setregid(0, 0) < 0)
849 errExit("setreuid/setregid");
850 errno = 0;
851
818 // FTW_PHYS - do not follow symbolic links 852 // FTW_PHYS - do not follow symbolic links
819 return nftw(path, remove_callback, 64, FTW_DEPTH | FTW_PHYS); 853 return nftw(path, remove_callback, 64, FTW_DEPTH | FTW_PHYS);
820} 854}