From f6100167d25ce0e1f53714c94d82da8fdfaf9975 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sun, 29 Apr 2018 09:21:16 -0400 Subject: whitelist haderning - based on an idea from smitsohu --- src/firejail/firejail.h | 10 ++++++++++ src/firejail/fs_whitelist.c | 19 +++++++++++++++++++ src/firejail/util.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 0df832c09..14f87c36c 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -524,6 +524,16 @@ unsigned extract_timeout(const char *str); void disable_file_or_dir(const char *fname); void disable_file_path(const char *path, const char *file); +// Get info regarding the last kernel mount operation. +// The return value points to a static area, and will be overwritten by subsequent calls. +// The function does an exit(1) if anything goes wrong. +typedef struct { + char *fsname; + char *dir; +} MountData; +MountData *get_last_mount(void); + + // fs_var.c void fs_var_log(void); // mounting /var/log void fs_var_lib(void); // various other fixes for software in /var directory diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 21fa8e624..2b63d949d 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -316,6 +316,16 @@ static void whitelist_path(ProfileEntry *entry) { if (mount(wfile, path, NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind"); + // check the last mount operation + MountData *mptr = get_last_mount(); // will do exit(1) if the mount cannot be found + + // No mounts are allowed on top level directories. A destination such as "/etc" is very bad! + // - there should be more than one '/' char in dest string + if (mptr->dir == strrchr(mptr->dir, '/')) { + fprintf(stderr, "Error: invalid mount on top of %s\n", mptr->dir); + exit(1); + } + free(wfile); return; @@ -856,6 +866,15 @@ void fs_whitelist(void) { fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link); else if (arg_debug || arg_debug_whitelists) printf("Created symbolic link %s -> %s\n", entry->link, entry->data + 10); + + // check again for files in /tmp directory + if (strncmp(entry->link, "/tmp/", 5) == 0) { + char *path = realpath(entry->link, NULL); + if (path == NULL || strncmp(path, "/tmp/", 5) != 0) { + fprintf(stderr, "Error: invalid symbolic link %s\n", entry->link); + exit(1); + } + } } } } diff --git a/src/firejail/util.c b/src/firejail/util.c index a44e52e98..f441f283f 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1029,3 +1029,39 @@ void disable_file_path(const char *path, const char *file) { free(fname); } +#define MAX_BUF 4096 +static char mbuf[MAX_BUF]; +static MountData mdata; + +// Get info regarding the last kernel mount operation. +// The return value points to a static area, and will be overwritten by subsequent calls. +// The function does an exit(1) if anything goes wrong. +MountData *get_last_mount(void) { + // open /proc/self/mounts + FILE *fp = fopen("/proc/self/mounts", "r"); + if (!fp) + goto errexit; + + mbuf[0] = '\0'; + while (fgets(mbuf, MAX_BUF, fp)); + fclose(fp); + if (arg_debug || arg_debug_whitelists) + printf("%s", mbuf); + + // there should be no reason to have a new mount on top of a top level directory + mdata.fsname = mbuf; + mdata.dir = strstr(mbuf, " "); + if (!mdata.dir) + goto errexit; + mdata.dir++; + char *end = strstr(mdata.dir, " "); + if (!end) + goto errexit; + *end = '\0'; + + return &mdata; + +errexit: + fprintf(stderr, "Error: cannot read /proc/self/mounts"); + exit(1); +} -- cgit v1.2.3-70-g09d2