From 30c9afe1085e8780f16e606a07f6381f7b47d108 Mon Sep 17 00:00:00 2001 From: Aleksey Manevich Date: Thu, 15 Sep 2016 19:59:20 +0300 Subject: /mnt whitelisting --- src/firejail/firejail.h | 2 ++ src/firejail/fs_whitelist.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index ed9d901c0..7043aa0ca 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -55,6 +55,7 @@ #define RUN_WHITELIST_HOME_USER_DIR "/run/firejail/mnt/orig-home-user" // home directory whitelisting #define RUN_WHITELIST_TMP_DIR "/run/firejail/mnt/orig-tmp" #define RUN_WHITELIST_MEDIA_DIR "/run/firejail/mnt/orig-media" +#define RUN_WHITELIST_MNT_DIR "/run/firejail/mnt/orig-mnt" #define RUN_WHITELIST_VAR_DIR "/run/firejail/mnt/orig-var" #define RUN_WHITELIST_DEV_DIR "/run/firejail/mnt/orig-dev" #define RUN_WHITELIST_OPT_DIR "/run/firejail/mnt/orig-opt" @@ -164,6 +165,7 @@ typedef struct profile_entry_t { unsigned home_dir:1; // whitelist in /home/user directory unsigned tmp_dir:1; // whitelist in /tmp directory unsigned media_dir:1; // whitelist in /media directory + unsigned mnt_dir:1; // whitelist in /mnt directory unsigned var_dir:1; // whitelist in /var directory unsigned dev_dir:1; // whitelist in /dev directory unsigned opt_dir:1; // whitelist in /opt directory diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 11e626b6e..ad7fea227 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -214,6 +214,16 @@ static void whitelist_path(ProfileEntry *entry) { if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_MEDIA_DIR, fname) == -1) errExit("asprintf"); } + else if (entry->mnt_dir) { + fname = path + 4; // strlen("/mnt") + if (*fname == '\0') { + fprintf(stderr, "Error: file %s is not in /mnt directory, exiting...\n", path); + exit(1); + } + + if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_MNT_DIR, fname) == -1) + errExit("asprintf"); + } else if (entry->var_dir) { fname = path + 4; // strlen("/var") if (*fname == '\0') { @@ -303,6 +313,7 @@ void fs_whitelist(void) { int home_dir = 0; // /home/user directory flag int tmp_dir = 0; // /tmp directory flag int media_dir = 0; // /media directory flag + int mnt_dir = 0; // /mnt directory flag int var_dir = 0; // /var directory flag int dev_dir = 0; // /dev directory flag int opt_dir = 0; // /opt directory flag @@ -368,6 +379,8 @@ void fs_whitelist(void) { tmp_dir = 1; else if (strncmp(new_name, "/media/", 7) == 0) media_dir = 1; + else if (strncmp(new_name, "/mnt/", 5) == 0) + mnt_dir = 1; else if (strncmp(new_name, "/var/", 5) == 0) var_dir = 1; else if (strncmp(new_name, "/dev/", 5) == 0) @@ -423,6 +436,16 @@ void fs_whitelist(void) { goto errexit; } } + else if (strncmp(new_name, "/mnt/", 5) == 0) { + entry->mnt_dir = 1; + mnt_dir = 1; + // both path and absolute path are under /mnt + if (strncmp(fname, "/mnt/", 5) != 0) { + if (arg_debug) + fprintf(stderr, "Debug %d: fname #%s#\n", __LINE__, fname); + goto errexit; + } + } else if (strncmp(new_name, "/var/", 5) == 0) { entry->var_dir = 1; var_dir = 1; @@ -580,6 +603,35 @@ void fs_whitelist(void) { media_dir = 0; } + // /mnt mountpoint + if (mnt_dir) { + // check if /mnt directory exists + struct stat s; + if (stat("/mnt", &s) == 0) { + // keep a copy of real /mnt directory in RUN_WHITELIST_MNT_DIR + int rv = mkdir(RUN_WHITELIST_MNT_DIR, 0755); + if (rv == -1) + errExit("mkdir"); + if (chown(RUN_WHITELIST_MNT_DIR, 0, 0) < 0) + errExit("chown"); + if (chmod(RUN_WHITELIST_MNT_DIR, 0755) < 0) + errExit("chmod"); + + if (mount("/mnt", RUN_WHITELIST_MNT_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) + errExit("mount bind"); + + // mount tmpfs on /mnt + if (arg_debug || arg_debug_whitelists) + printf("Mounting tmpfs on /mnt directory\n"); + if (mount("tmpfs", "/mnt", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) + errExit("mounting tmpfs on /mnt"); + fs_logger("tmpfs /mnt"); + } + else + mnt_dir = 0; + } + + // /var mountpoint if (var_dir) { // keep a copy of real /var directory in RUN_WHITELIST_VAR_DIR @@ -730,6 +782,13 @@ void fs_whitelist(void) { fs_logger2("tmpfs", RUN_WHITELIST_MEDIA_DIR); } + // mask the real /mnt directory, currently mounted on RUN_WHITELIST_MNT_DIR + if (mnt_dir) { + if (mount("tmpfs", RUN_WHITELIST_MNT_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) + errExit("mount tmpfs"); + fs_logger2("tmpfs", RUN_WHITELIST_MNT_DIR); + } + if (new_name) free(new_name); -- cgit v1.2.3-54-g00ecf From a7c2e4aa3fab87112bed6675a3ad75f68e191b6e Mon Sep 17 00:00:00 2001 From: Aleksey Manevich Date: Thu, 15 Sep 2016 21:17:50 +0300 Subject: update man --- src/man/firejail-profile.txt | 2 +- src/man/firejail.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index d4ab0af55..5a959dd83 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -207,7 +207,7 @@ Blacklist violations logged to syslog. Whitelist directory or file. A temporary file system is mounted on the top directory, and the whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, everything else is discarded when the sandbox is closed. The top directory could be -user home, /dev, /media, /opt, /var, and /tmp. +user home, /dev, /media, /mnt, /opt, /var, and /tmp. .br .br diff --git a/src/man/firejail.txt b/src/man/firejail.txt index c05c8e201..d654290bf 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -1582,7 +1582,7 @@ firejail version 0.9.27 Whitelist directory or file. A temporary file system is mounted on the top directory, and the whitelisted files are mount-binded inside. Modifications to whitelisted files are persistent, everything else is discarded when the sandbox is closed. The top directory could be -user home, /dev, /media, /opt, /var, and /tmp. +user home, /dev, /media, /mnt, /opt, /var, and /tmp. .br .br -- cgit v1.2.3-54-g00ecf