From 980979d77ebd30ca1d6b518d48068a1e3660a4e8 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sun, 16 Aug 2015 08:56:48 -0400 Subject: --overlay rework, adding a persistent directory; implemented --overlay-tmpfs option --- src/firejail/firejail.h | 7 ++++-- src/firejail/fs.c | 57 ++++++++++++++++++++++++------------------------- src/firejail/main.c | 35 +++++++++++++++++++++++++++++- src/firejail/usage.c | 14 ++++++++++-- src/man/firejail.txt | 21 +++++++++++++++--- 5 files changed, 97 insertions(+), 37 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index a1833b4bc..7eb4786e6 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -26,7 +26,6 @@ #define RO_DIR "/tmp/firejail/firejail.ro.dir" #define RO_FILE "/tmp/firejail/firejail.ro.file" #define MNT_DIR "/tmp/firejail/mnt" -#define OVERLAY_DIR "/tmp/firejail/overlay" #define HOME_DIR "/tmp/firejail/mnt/home" #define ETC_DIR "/tmp/firejail/mnt/etc" #define MAX_INCLUDE_LEVEL 6 @@ -70,6 +69,7 @@ typedef struct config_t { char *home_private_keep; // keep list for private home directory char *etc_private_keep; // keep list for private etc directory char *cwd; // current working directory + char *overlay_dir; // networking char *hostname; @@ -109,11 +109,13 @@ static inline int any_bridge_configured(void) { else return 0; } + extern int arg_private; // mount private /home and /tmp directory extern int arg_debug; // print debug messages extern int arg_nonetwork; // --net=none extern int arg_command; // -c -extern int arg_overlay; // --overlay +extern int arg_overlay; // overlay option +extern int arg_overlay_keep; // place overlay diff directory in ~/.firejail extern int arg_zsh; // use zsh as default shell extern int arg_csh; // use csh as default shell @@ -358,3 +360,4 @@ void fs_check_etc_list(void); void fs_private_etc_list(void); #endif + diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 5b8093885..c38317371 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -82,30 +82,6 @@ void fs_build_mnt_dir(void) { } } -// build /tmp/firejail/overlay directory -void fs_build_overlay_dir(void) { - struct stat s; - fs_build_firejail_dir(); - - // create /tmp/firejail directory - if (stat(OVERLAY_DIR, &s)) { - if (arg_debug) - printf("Creating %s directory\n", MNT_DIR); - /* coverity[toctou] */ - int rv = mkdir(OVERLAY_DIR, S_IRWXU | S_IRWXG | S_IRWXO); - if (rv == -1) - errExit("mkdir"); - if (chown(OVERLAY_DIR, 0, 0) < 0) - errExit("chown"); - if (chmod(OVERLAY_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) - errExit("chmod"); - } -} - - - - - //*********************************************** // process profile file //*********************************************** @@ -629,8 +605,25 @@ void fs_overlayfs(void) { if (chmod(oroot, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) errExit("chmod"); + char *basedir = MNT_DIR; + if (arg_overlay_keep) { + // check the directory exists + struct stat s; + if (stat("/myoverlay", &s) == -1) { + fprintf(stderr, "Error: overlay directory should already exist\n"); + exit(1); + } + + // set base for working and diff directories + basedir = cfg.overlay_dir; + if (mkdir(basedir, S_IRWXU | S_IRWXG | S_IRWXO) != 0) { + fprintf(stderr, "Error: cannot create overlay directory\n"); + exit(1); + } + } + char *odiff; - if(asprintf(&odiff, "%s/odiff", MNT_DIR) == -1) + if(asprintf(&odiff, "%s/odiff", basedir) == -1) errExit("asprintf"); if (mkdir(odiff, S_IRWXU | S_IRWXG | S_IRWXO)) errExit("mkdir"); @@ -638,9 +631,9 @@ void fs_overlayfs(void) { errExit("chown"); if (chmod(odiff, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) errExit("chmod"); - + char *owork; - if(asprintf(&owork, "%s/owork", MNT_DIR) == -1) + if(asprintf(&owork, "%s/owork", basedir) == -1) errExit("asprintf"); if (mkdir(owork, S_IRWXU | S_IRWXG | S_IRWXO)) errExit("mkdir"); @@ -648,12 +641,16 @@ void fs_overlayfs(void) { errExit("chown"); if (chmod(owork, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) errExit("chmod"); - + // mount overlayfs if (arg_debug) printf("Mounting OverlayFS\n"); char *option; if (oldkernel) { // old Ubuntu/OpenSUSE kernels + if (arg_overlay_keep) { + fprintf(stderr, "Error: option --overlay= not available for kernels older than 3.18\n"); + exit(1); + } if (asprintf(&option, "lowerdir=/,upperdir=%s", odiff) == -1) errExit("asprintf"); if (mount("overlayfs", oroot, "overlayfs", MS_MGC_VAL, option) < 0) @@ -662,10 +659,12 @@ void fs_overlayfs(void) { else { // kernel 3.18 or newer if (asprintf(&option, "lowerdir=/,upperdir=%s,workdir=%s", odiff, owork) == -1) errExit("asprintf"); +//printf("option #%s#\n", option); if (mount("overlay", oroot, "overlay", MS_MGC_VAL, option) < 0) errExit("mounting overlayfs"); } - + printf("OverlayFS configured in %s directory\n", basedir); + // mount-bind dev directory if (arg_debug) printf("Mounting /dev\n"); diff --git a/src/firejail/main.c b/src/firejail/main.c index 6c5d9a44e..3c7a8401e 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -52,7 +52,8 @@ int arg_private = 0; // mount private /home and /tmp directoryu int arg_debug = 0; // print debug messages int arg_nonetwork = 0; // --net=none int arg_command = 0; // -c -int arg_overlay = 0; // --overlay +int arg_overlay = 0; // overlay option +int arg_overlay_keep = 0; // place overlay diff directory in ~/.firejail int arg_zsh = 0; // use zsh as default shell int arg_csh = 0; // use csh as default shell @@ -625,6 +626,38 @@ int main(int argc, char **argv) { exit(1); } arg_overlay = 1; + arg_overlay_keep = 1; + + // create ~/.firejail directory + char *dirname; + if (asprintf(&dirname, "%s/.firejail", cfg.homedir) == -1) + errExit("asprintf"); + struct stat s; + if (stat(dirname, &s) == -1) { + if (mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO)) + errExit("mkdir"); + if (chown(dirname, getuid(), getgid()) < 0) + errExit("chown"); + if (chmod(dirname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) + errExit("chmod"); + } + free(dirname); + + // check overlay directory + if (asprintf(&dirname, "%s/.firejail/%d", cfg.homedir, getpid()) == -1) + errExit("asprintf"); + if (stat(dirname, &s) == 0) { + fprintf(stderr, "Error: overlay directory already exists: %s\n", dirname); + exit(1); + } + cfg.overlay_dir = dirname; + } + else if (strcmp(argv[i], "--overlay-tmpfs") == 0) { + if (cfg.chrootdir) { + fprintf(stderr, "Error: --overlay and --chroot options are mutually exclusive\n"); + exit(1); + } + arg_overlay = 1; } else if (strncmp(argv[i], "--profile=", 10) == 0) { // multiple profile files are allowed! diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 3ddd85aac..9aeb5895d 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -140,9 +140,19 @@ void usage(void) { printf("\t\tlogfile, and keep the size of the file under 500KB using log\n"); printf("\t\trotation. Five files with prefixes .1 to .5 are used in\n"); printf("\t\trotation.\n\n"); + printf("\t--overlay - mount a filesystem overlay on top of the current filesystem.\n"); - printf("\t\t(OverlayFS support is required in Linux kernel for this option\n"); - printf("\t\tto work)\n\n"); + printf("\t\tThe upper filesystem layer is persistent, and stored in\n"); + printf("\t\t$HOME/.firejail directory. (OverlayFS support is required in\n"); + printf("\t\tLinux kernel for this option to work). \n\n"); + + printf("\t--overlay-tmpfs - mount a filesystem overlay on top of the current\n"); + printf("\t\tfilesystem. The upper layer is stored in a tmpfs filesystem,\n"); + printf("\t\tand it is discarded when the sandbox is closed. (OverlayFS\n"); + printf("\t\tsupport is required in Linux kernel for this option to work).\n\n"); + + + printf("\t--private - mount new /root and /home/user directories in temporary\n"); printf("\t\tfilesystems. All modifications are discarded when the sandbox is\n"); diff --git a/src/man/firejail.txt b/src/man/firejail.txt index fe2a909c9..3e399db72 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -602,20 +602,35 @@ $ ls -l sandboxlog* .TP \fB\-\-overlay +Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay. +The overlay is stored in $HOME/.firejail directory. +.br + +.br +OverlayFS support is required in Linux kernel for this option to work. +OverlayFS was officially introduced in Linux kernel version 3.18 +.br + +.br +Example: +.br +$ firejail \-\-overlay firefox + +.TP +\fB\-\-overlay-tmpfs Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay, and are discarded when the sandbox is closed. .br .br OverlayFS support is required in Linux kernel for this option to work. -OverlayFS was officially introduced in Linux kernel version 3.18. It was also -available in earlier kernel versions in some distributions such as Ubuntu and OpenSUSE. +OverlayFS was officially introduced in Linux kernel version 3.18 .br .br Example: .br -$ firejail \-\-overlay firefox +$ firejail \-\-overlay-tmpfs firefox .TP \fB\-\-private -- cgit v1.2.3-54-g00ecf