aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs.c54
-rw-r--r--src/firejail/main.c100
-rw-r--r--src/firejail/usage.c18
-rw-r--r--src/man/firejail.txt44
5 files changed, 176 insertions, 43 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 16b9d468f..ee70f19f1 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -221,7 +221,8 @@ extern int arg_debug_whitelists; // print debug messages for whitelists
221extern int arg_nonetwork; // --net=none 221extern int arg_nonetwork; // --net=none
222extern int arg_command; // -c 222extern int arg_command; // -c
223extern int arg_overlay; // overlay option 223extern int arg_overlay; // overlay option
224extern int arg_overlay_keep; // place overlay diff directory in ~/.firejail 224extern int arg_overlay_keep; // place overlay diff in a known directory
225extern int arg_overlay_reuse; // allow the reuse of overlays
225extern int arg_zsh; // use zsh as default shell 226extern int arg_zsh; // use zsh as default shell
226extern int arg_csh; // use csh as default shell 227extern int arg_csh; // use csh as default shell
227 228
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 86126672e..c152abe0d 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -879,21 +879,37 @@ void fs_overlayfs(void) {
879 if (chmod(oroot, 0755) < 0) 879 if (chmod(oroot, 0755) < 0)
880 errExit("chmod"); 880 errExit("chmod");
881 881
882 struct stat s;
882 char *basedir = RUN_MNT_DIR; 883 char *basedir = RUN_MNT_DIR;
883 if (arg_overlay_keep) { 884 if (arg_overlay_keep) {
884 // set base for working and diff directories 885 // set base for working and diff directories
885 basedir = cfg.overlay_dir; 886 basedir = cfg.overlay_dir;
886 if (mkdir(basedir, 0755) != 0) { 887
887 fprintf(stderr, "Error: cannot create overlay directory\n"); 888 // does the overlay exist?
888 exit(1); 889 if (stat(basedir, &s) == 0) {
890 if (arg_overlay_reuse == 0) {
891 fprintf(stderr, "Error: overlay directory exists, but reuse is not allowed\n");
892 exit(1);
893 }
894 }
895 else {
896 if (mkdir(basedir, 0755) != 0) {
897 fprintf(stderr, "Error: cannot create overlay directory\n");
898 exit(1);
899 }
889 } 900 }
890 } 901 }
891 902
892 char *odiff; 903 char *odiff;
893 if(asprintf(&odiff, "%s/odiff", basedir) == -1) 904 if(asprintf(&odiff, "%s/odiff", basedir) == -1)
894 errExit("asprintf"); 905 errExit("asprintf");
895 if (mkdir(odiff, 0755)) 906
896 errExit("mkdir"); 907 // no need to check arg_overlay_reuse
908 if (stat(odiff, &s) != 0) {
909 if (mkdir(odiff, 0755))
910 errExit("mkdir");
911 }
912
897 if (chown(odiff, 0, 0) < 0) 913 if (chown(odiff, 0, 0) < 0)
898 errExit("chown"); 914 errExit("chown");
899 if (chmod(odiff, 0755) < 0) 915 if (chmod(odiff, 0755) < 0)
@@ -902,8 +918,13 @@ void fs_overlayfs(void) {
902 char *owork; 918 char *owork;
903 if(asprintf(&owork, "%s/owork", basedir) == -1) 919 if(asprintf(&owork, "%s/owork", basedir) == -1)
904 errExit("asprintf"); 920 errExit("asprintf");
905 if (mkdir(owork, 0755)) 921
906 errExit("mkdir"); 922 // no need to check arg_overlay_reuse
923 if (stat(owork, &s) != 0) {
924 if (mkdir(owork, 0755))
925 errExit("mkdir");
926 }
927
907 if (chown(owork, 0, 0) < 0) 928 if (chown(owork, 0, 0) < 0)
908 errExit("chown"); 929 errExit("chown");
909 if (chmod(owork, 0755) < 0) 930 if (chmod(owork, 0755) < 0)
@@ -959,8 +980,13 @@ void fs_overlayfs(void) {
959 980
960 if(asprintf(&hdiff, "%s/hdiff", basedir) == -1) 981 if(asprintf(&hdiff, "%s/hdiff", basedir) == -1)
961 errExit("asprintf"); 982 errExit("asprintf");
962 if (mkdir(hdiff, S_IRWXU | S_IRWXG | S_IRWXO)) 983
963 errExit("mkdir"); 984 // no need to check arg_overlay_reuse
985 if (stat(hdiff, &s) != 0) {
986 if (mkdir(hdiff, S_IRWXU | S_IRWXG | S_IRWXO))
987 errExit("mkdir");
988 }
989
964 if (chown(hdiff, 0, 0) < 0) 990 if (chown(hdiff, 0, 0) < 0)
965 errExit("chown"); 991 errExit("chown");
966 if (chmod(hdiff, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) 992 if (chmod(hdiff, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
@@ -968,8 +994,13 @@ void fs_overlayfs(void) {
968 994
969 if(asprintf(&hwork, "%s/hwork", basedir) == -1) 995 if(asprintf(&hwork, "%s/hwork", basedir) == -1)
970 errExit("asprintf"); 996 errExit("asprintf");
971 if (mkdir(hwork, S_IRWXU | S_IRWXG | S_IRWXO)) 997
972 errExit("mkdir"); 998 // no need to check arg_overlay_reuse
999 if (stat(hwork, &s) != 0) {
1000 if (mkdir(hwork, S_IRWXU | S_IRWXG | S_IRWXO))
1001 errExit("mkdir");
1002 }
1003
973 if (chown(hwork, 0, 0) < 0) 1004 if (chown(hwork, 0, 0) < 0)
974 errExit("chown"); 1005 errExit("chown");
975 if (chmod(hwork, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) 1006 if (chmod(hwork, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0)
@@ -1011,7 +1042,6 @@ void fs_overlayfs(void) {
1011 fs_logger("whitelist /run"); 1042 fs_logger("whitelist /run");
1012 1043
1013 // mount-bind /tmp/.X11-unix directory 1044 // mount-bind /tmp/.X11-unix directory
1014 struct stat s;
1015 if (stat("/tmp/.X11-unix", &s) == 0) { 1045 if (stat("/tmp/.X11-unix", &s) == 0) {
1016 if (arg_debug) 1046 if (arg_debug)
1017 printf("Mounting /tmp/.X11-unix\n"); 1047 printf("Mounting /tmp/.X11-unix\n");
diff --git a/src/firejail/main.c b/src/firejail/main.c
index acae7c3dd..120809456 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -59,7 +59,8 @@ int arg_debug_whitelists; // print debug messages for whitelists
59int arg_nonetwork = 0; // --net=none 59int arg_nonetwork = 0; // --net=none
60int arg_command = 0; // -c 60int arg_command = 0; // -c
61int arg_overlay = 0; // overlay option 61int arg_overlay = 0; // overlay option
62int arg_overlay_keep = 0; // place overlay diff directory in ~/.firejail 62int arg_overlay_keep = 0; // place overlay diff in a known directory
63int arg_overlay_reuse = 0; // allow the reuse of overlays
63int arg_zsh = 0; // use zsh as default shell 64int arg_zsh = 0; // use zsh as default shell
64int arg_csh = 0; // use csh as default shell 65int arg_csh = 0; // use csh as default shell
65 66
@@ -691,6 +692,41 @@ static void delete_x11_file(pid_t pid) {
691 free(fname); 692 free(fname);
692} 693}
693 694
695static char *create_and_check_overlay_dir(const char *subdirname, int allow_reuse) {
696 // create ~/.firejail directory
697 struct stat s;
698 char *dirname;
699 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
700 errExit("asprintf");
701 if (stat(dirname, &s) == -1) {
702 /* coverity[toctou] */
703 if (mkdir(dirname, 0700))
704 errExit("mkdir");
705 if (chown(dirname, getuid(), getgid()) < 0)
706 errExit("chown");
707 if (chmod(dirname, 0700) < 0)
708 errExit("chmod");
709 }
710 else if (is_link(dirname)) {
711 fprintf(stderr, "Error: invalid ~/.firejail directory\n");
712 exit(1);
713 }
714
715 free(dirname);
716
717 // check overlay directory
718 if (asprintf(&dirname, "%s/.firejail/%s", cfg.homedir, subdirname) == -1)
719 errExit("asprintf");
720 if (allow_reuse == 0) {
721 if (stat(dirname, &s) == 0) {
722 fprintf(stderr, "Error: overlay directory already exists: %s\n", dirname);
723 exit(1);
724 }
725 }
726
727 return dirname;
728}
729
694static void detect_quiet(int argc, char **argv) { 730static void detect_quiet(int argc, char **argv) {
695 int i; 731 int i;
696 732
@@ -1193,34 +1229,54 @@ int main(int argc, char **argv) {
1193 arg_overlay = 1; 1229 arg_overlay = 1;
1194 arg_overlay_keep = 1; 1230 arg_overlay_keep = 1;
1195 1231
1196 // create ~/.firejail directory 1232 char *subdirname;
1197 char *dirname; 1233 if (asprintf(&subdirname, "%d", getpid()) == -1)
1198 if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1)
1199 errExit("asprintf"); 1234 errExit("asprintf");
1200 if (stat(dirname, &s) == -1) { 1235 cfg.overlay_dir = create_and_check_overlay_dir(subdirname, arg_overlay_reuse);
1201 /* coverity[toctou] */ 1236
1202 if (mkdir(dirname, 0700)) 1237 free(subdirname);
1203 errExit("mkdir"); 1238 }
1204 if (chown(dirname, getuid(), getgid()) < 0) 1239 else if (strncmp(argv[i], "--overlay-named=", 16) == 0) {
1205 errExit("chown"); 1240 if (cfg.chrootdir) {
1206 if (chmod(dirname, 0700) < 0) 1241 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1207 errExit("chmod"); 1242 exit(1);
1208 } 1243 }
1209 else if (is_link(dirname)) { 1244 struct stat s;
1210 fprintf(stderr, "Error: invalid ~/.firejail directory\n"); 1245 if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
1246 fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
1211 exit(1); 1247 exit(1);
1212 } 1248 }
1249 arg_overlay = 1;
1250 arg_overlay_keep = 1;
1251 arg_overlay_reuse = 1;
1213 1252
1214 free(dirname); 1253 char *subdirname = argv[i] + 16;
1254 if (subdirname == '\0') {
1255 fprintf(stderr, "Error: invalid overlay option\n");
1256 exit(1);
1257 }
1258 cfg.overlay_dir = create_and_check_overlay_dir(subdirname, arg_overlay_reuse);
1259 }
1260 else if (strncmp(argv[i], "--overlay-path=", 15) == 0) {
1261 if (cfg.chrootdir) {
1262 fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n");
1263 exit(1);
1264 }
1265 struct stat s;
1266 if (stat("/proc/sys/kernel/grsecurity", &s) == 0) {
1267 fprintf(stderr, "Error: --overlay option is not available on Grsecurity systems\n");
1268 exit(1);
1269 }
1270 arg_overlay = 1;
1271 arg_overlay_keep = 1;
1272 arg_overlay_reuse = 1;
1215 1273
1216 // check overlay directory 1274 char *dirname = argv[i] + 15;
1217 if (asprintf(&dirname, "%s/.firejail/%d", cfg.homedir, getpid()) == -1) 1275 if (dirname == '\0') {
1218 errExit("asprintf"); 1276 fprintf(stderr, "Error: invalid overlay option\n");
1219 if (stat(dirname, &s) == 0) {
1220 fprintf(stderr, "Error: overlay directory already exists: %s\n", dirname);
1221 exit(1); 1277 exit(1);
1222 } 1278 }
1223 cfg.overlay_dir = dirname; 1279 cfg.overlay_dir = expand_home(dirname, cfg.homedir);
1224 } 1280 }
1225 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) { 1281 else if (strcmp(argv[i], "--overlay-tmpfs") == 0) {
1226 if (cfg.chrootdir) { 1282 if (cfg.chrootdir) {
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 03558cca7..ed6d22e69 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -176,16 +176,26 @@ void usage(void) {
176 176
177 printf(" --overlay - mount a filesystem overlay on top of the current filesystem.\n"); 177 printf(" --overlay - mount a filesystem overlay on top of the current filesystem.\n");
178 printf("\tThe upper filesystem layer is persistent, and stored in\n"); 178 printf("\tThe upper filesystem layer is persistent, and stored in\n");
179 printf("\t$HOME/.firejail directory. (OverlayFS support is required in\n"); 179 printf("\t$HOME/.firejail/<PID> directory. (OverlayFS support is required in\n");
180 printf("\tLinux kernel for this option to work). \n\n"); 180 printf("\tLinux kernel for this option to work). \n\n");
181
182 printf(" --overlay-named=name - mount a filesystem overlay on top of the current\n");
183 printf("\tfilesystem. The upper filesystem layer is persistent, and stored in\n");
184 printf("\t$HOME/.firejail/<NAME> directory. (OverlayFS support is required in\n");
185 printf("\tLinux kernel for this option to work). \n\n");
186
187 printf(" --overlay-path=path - mount a filesystem overlay on top of the current\n");
188 printf("\tfilesystem. The upper filesystem layer is persistent, and stored in\n");
189 printf("\tthe specified path. (OverlayFS support is required in Linux kernel for\n");
190 printf("\tthis option to work). \n\n");
181 191
182 printf(" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n\n");
183
184 printf(" --overlay-tmpfs - mount a filesystem overlay on top of the current\n"); 192 printf(" --overlay-tmpfs - mount a filesystem overlay on top of the current\n");
185 printf("\tfilesystem. The upper layer is stored in a tmpfs filesystem,\n"); 193 printf("\tfilesystem. The upper layer is stored in a tmpfs filesystem,\n");
186 printf("\tand it is discarded when the sandbox is closed. (OverlayFS\n"); 194 printf("\tand it is discarded when the sandbox is closed. (OverlayFS\n");
187 printf("\tsupport is required in Linux kernel for this option to work).\n\n"); 195 printf("\tsupport is required in Linux kernel for this option to work).\n\n");
188 196
197 printf(" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n\n");
198
189 printf(" --private - mount new /root and /home/user directories in temporary\n"); 199 printf(" --private - mount new /root and /home/user directories in temporary\n");
190 printf("\tfilesystems. All modifications are discarded when the sandbox is\n"); 200 printf("\tfilesystems. All modifications are discarded when the sandbox is\n");
191 printf("\tclosed.\n\n"); 201 printf("\tclosed.\n\n");
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index fb8cb630b..3cc9a8401 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -994,7 +994,7 @@ $ ls -l sandboxlog*
994\fB\-\-overlay 994\fB\-\-overlay
995Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container, 995Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container,
996the system directories are mounted read-write. All filesystem modifications go into the overlay. 996the system directories are mounted read-write. All filesystem modifications go into the overlay.
997The overlay is stored in $HOME/.firejail directory. This option is not available on Grsecurity systems. 997The overlay is stored in $HOME/.firejail/<PID> directory. This option is not available on Grsecurity systems.
998.br 998.br
999 999
1000.br 1000.br
@@ -1008,14 +1008,40 @@ Example:
1008$ firejail \-\-overlay firefox 1008$ firejail \-\-overlay firefox
1009 1009
1010.TP 1010.TP
1011\fB\-\-overlay-clean 1011\fB\-\-overlay-named=name
1012Clean all overlays stored in $HOME/.firejail directory. 1012Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container,
1013the system directories are mounted read-write. All filesystem modifications go into the overlay.
1014The overlay is stored in $HOME/.firejail/<NAME> directory. The created overlay can be reused between multiple
1015sessions. This option is not available on Grsecurity systems.
1016.br
1017
1018.br
1019OverlayFS support is required in Linux kernel for this option to work.
1020OverlayFS was officially introduced in Linux kernel version 3.18
1013.br 1021.br
1014 1022
1015.br 1023.br
1016Example: 1024Example:
1017.br 1025.br
1018$ firejail \-\-overlay-clean 1026$ firejail \-\-overlay-named=jail1 firefox
1027
1028.TP
1029\fB\-\-overlay-path=path
1030Mount a filesystem overlay on top of the current filesystem. Unlike the regular filesystem container,
1031the system directories are mounted read-write. All filesystem modifications go into the overlay.
1032The overlay is stored in the specified path. The created overlay can be reused between multiple sessions.
1033This option is not available on Grsecurity systems.
1034.br
1035
1036.br
1037OverlayFS support is required in Linux kernel for this option to work.
1038OverlayFS was officially introduced in Linux kernel version 3.18
1039.br
1040
1041.br
1042Example:
1043.br
1044$ firejail \-\-overlay-path=~/jails/jail1 firefox
1019 1045
1020.TP 1046.TP
1021\fB\-\-overlay-tmpfs 1047\fB\-\-overlay-tmpfs
@@ -1034,6 +1060,16 @@ Example:
1034$ firejail \-\-overlay-tmpfs firefox 1060$ firejail \-\-overlay-tmpfs firefox
1035 1061
1036.TP 1062.TP
1063\fB\-\-overlay-clean
1064Clean all overlays stored in $HOME/.firejail directory.
1065.br
1066
1067.br
1068Example:
1069.br
1070$ firejail \-\-overlay-clean
1071
1072.TP
1037\fB\-\-private 1073\fB\-\-private
1038Mount new /root and /home/user directories in temporary 1074Mount new /root and /home/user directories in temporary
1039filesystems. All modifications are discarded when the sandbox is 1075filesystems. All modifications are discarded when the sandbox is