diff options
author | 2017-07-19 17:52:15 +0300 | |
---|---|---|
committer | 2017-07-19 17:57:08 +0300 | |
commit | 6a3af56b8cb121884ac3934f50011c46dc6680e4 (patch) | |
tree | d1895ea8228db1959a64b2caad9c0c12ac6026ed | |
parent | support for Xephyr screen size (diff) | |
download | firejail-6a3af56b8cb121884ac3934f50011c46dc6680e4.tar.gz firejail-6a3af56b8cb121884ac3934f50011c46dc6680e4.tar.zst firejail-6a3af56b8cb121884ac3934f50011c46dc6680e4.zip |
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.
-rw-r--r-- | src/firejail/fs.c | 31 |
1 files changed, 28 insertions, 3 deletions
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 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include <sys/mount.h> | 21 | #include <sys/mount.h> |
22 | #include <sys/stat.h> | 22 | #include <sys/stat.h> |
23 | #include <sys/statvfs.h> | ||
23 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
24 | #include <linux/limits.h> | 25 | #include <linux/limits.h> |
25 | #include <fnmatch.h> | 26 | #include <fnmatch.h> |
@@ -414,6 +415,15 @@ void fs_blacklist(void) { | |||
414 | free(noblacklist); | 415 | free(noblacklist); |
415 | } | 416 | } |
416 | 417 | ||
418 | static int get_mount_flags(const char *path, unsigned long *flags) { | ||
419 | struct statvfs buf; | ||
420 | |||
421 | if (statvfs(path, &buf) < 0) | ||
422 | return -errno; | ||
423 | *flags = buf.f_flag; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
417 | //*********************************************** | 427 | //*********************************************** |
418 | // mount namespace | 428 | // mount namespace |
419 | //*********************************************** | 429 | //*********************************************** |
@@ -425,10 +435,15 @@ void fs_rdonly(const char *dir) { | |||
425 | struct stat s; | 435 | struct stat s; |
426 | int rv = stat(dir, &s); | 436 | int rv = stat(dir, &s); |
427 | if (rv == 0) { | 437 | if (rv == 0) { |
438 | unsigned long flags = 0; | ||
439 | get_mount_flags(dir, &flags); | ||
440 | if ((flags & MS_RDONLY) == MS_RDONLY) | ||
441 | return; | ||
442 | flags |= MS_RDONLY; | ||
428 | // mount --bind /bin /bin | 443 | // mount --bind /bin /bin |
429 | // mount --bind -o remount,ro /bin | 444 | // mount --bind -o remount,ro /bin |
430 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 445 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
431 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL) < 0) | 446 | mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) |
432 | errExit("mount read-only"); | 447 | errExit("mount read-only"); |
433 | fs_logger2("read-only", dir); | 448 | fs_logger2("read-only", dir); |
434 | } | 449 | } |
@@ -449,8 +464,13 @@ static void fs_rdwr(const char *dir) { | |||
449 | 464 | ||
450 | // mount --bind /bin /bin | 465 | // mount --bind /bin /bin |
451 | // mount --bind -o remount,rw /bin | 466 | // mount --bind -o remount,rw /bin |
467 | unsigned long flags = 0; | ||
468 | get_mount_flags(dir, &flags); | ||
469 | if ((flags & MS_RDONLY) == 0) | ||
470 | return; | ||
471 | flags &= ~MS_RDONLY; | ||
452 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 472 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
453 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | 473 | mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) |
454 | errExit("mount read-write"); | 474 | errExit("mount read-write"); |
455 | fs_logger2("read-write", dir); | 475 | fs_logger2("read-write", dir); |
456 | } | 476 | } |
@@ -464,8 +484,13 @@ void fs_noexec(const char *dir) { | |||
464 | if (rv == 0) { | 484 | if (rv == 0) { |
465 | // mount --bind /bin /bin | 485 | // mount --bind /bin /bin |
466 | // mount --bind -o remount,ro /bin | 486 | // mount --bind -o remount,ro /bin |
487 | unsigned long flags = 0; | ||
488 | get_mount_flags(dir, &flags); | ||
489 | if ((flags & (MS_NOEXEC|MS_NODEV|MS_NOSUID)) == (MS_NOEXEC|MS_NODEV|MS_NOSUID)) | ||
490 | return; | ||
491 | flags |= MS_NOEXEC|MS_NODEV|MS_NOSUID; | ||
467 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 492 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || |
468 | mount(NULL, dir, NULL, MS_BIND|MS_REMOUNT|MS_NOEXEC|MS_NODEV|MS_NOSUID|MS_REC, NULL) < 0) | 493 | mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) |
469 | errExit("mount noexec"); | 494 | errExit("mount noexec"); |
470 | fs_logger2("noexec", dir); | 495 | fs_logger2("noexec", dir); |
471 | } | 496 | } |