From 6a3af56b8cb121884ac3934f50011c46dc6680e4 Mon Sep 17 00:00:00 2001 From: Topi Miettinen Date: Wed, 19 Jul 2017 17:52:15 +0300 Subject: Improve mount handling noexec/read-only/read-write handling: copy underlying FS flags before remounting. If the flags are already OK, don't remount unnecessarily. --- src/firejail/fs.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/firejail/fs.c b/src/firejail/fs.c index c60322dda..53f840455 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -20,6 +20,7 @@ #include "firejail.h" #include #include +#include #include #include #include @@ -414,6 +415,15 @@ void fs_blacklist(void) { free(noblacklist); } +static int get_mount_flags(const char *path, unsigned long *flags) { + struct statvfs buf; + + if (statvfs(path, &buf) < 0) + return -errno; + *flags = buf.f_flag; + return 0; +} + //*********************************************** // mount namespace //*********************************************** @@ -425,10 +435,15 @@ void fs_rdonly(const char *dir) { struct stat s; int rv = stat(dir, &s); if (rv == 0) { + unsigned long flags = 0; + get_mount_flags(dir, &flags); + if ((flags & MS_RDONLY) == MS_RDONLY) + return; + flags |= MS_RDONLY; // mount --bind /bin /bin // mount --bind -o remount,ro /bin if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || - mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) + mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) errExit("mount read-only"); fs_logger2("read-only", dir); } @@ -449,8 +464,13 @@ static void fs_rdwr(const char *dir) { // mount --bind /bin /bin // mount --bind -o remount,rw /bin + unsigned long flags = 0; + get_mount_flags(dir, &flags); + if ((flags & MS_RDONLY) == 0) + return; + flags &= ~MS_RDONLY; if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || - mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) + mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) errExit("mount read-write"); fs_logger2("read-write", dir); } @@ -464,8 +484,13 @@ void fs_noexec(const char *dir) { if (rv == 0) { // mount --bind /bin /bin // mount --bind -o remount,ro /bin + unsigned long flags = 0; + get_mount_flags(dir, &flags); + if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID)) + return; + flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID; if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || - mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) + mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) errExit("mount noexec"); fs_logger2("noexec", dir); } -- cgit v1.2.3-54-g00ecf