diff options
author | smitsohu <smitsohu@gmail.com> | 2018-05-11 00:58:11 +0200 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2018-05-11 00:58:11 +0200 |
commit | 392bedba292d058052157d672129545fdcafdb83 (patch) | |
tree | 9cdd8cc653a0e204441f8a0378dd7e977dad80b3 | |
parent | Merge branch 'master' of https://github.com/netblue30/firejail (diff) | |
download | firejail-392bedba292d058052157d672129545fdcafdb83.tar.gz firejail-392bedba292d058052157d672129545fdcafdb83.tar.zst firejail-392bedba292d058052157d672129545fdcafdb83.zip |
harden read-write mounts, cleanup
-rw-r--r-- | src/firejail/fs.c | 57 | ||||
-rw-r--r-- | src/firejail/pulseaudio.c | 8 | ||||
-rw-r--r-- | src/firejail/x11.c | 9 |
3 files changed, 45 insertions, 29 deletions
diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 88f92ad74..f3ed67928 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c | |||
@@ -484,29 +484,44 @@ void fs_rdonly(const char *dir) { | |||
484 | 484 | ||
485 | static void fs_rdwr(const char *dir) { | 485 | static void fs_rdwr(const char *dir) { |
486 | assert(dir); | 486 | assert(dir); |
487 | // check directory exists | 487 | // check directory exists and ensure we have a resolved path |
488 | // the resolved path allows to run a sanity check after the mount | ||
489 | char *path = realpath(dir, NULL); | ||
490 | if (path == NULL) | ||
491 | return; | ||
492 | // allow only user owned directories, except the user is root | ||
493 | uid_t u = getuid(); | ||
488 | struct stat s; | 494 | struct stat s; |
489 | int rv = stat(dir, &s); | 495 | int rv = stat(path, &s); |
490 | if (rv == 0) { | 496 | if (rv) { |
491 | // if the file is outside /home directory, allow only root user | 497 | free(path); |
492 | uid_t u = getuid(); | 498 | return; |
493 | if (u != 0 && s.st_uid != u) { | 499 | } |
494 | fwarning("you are not allowed to change %s to read-write\n", dir); | 500 | if (u != 0 && s.st_uid != u) { |
495 | return; | 501 | fwarning("you are not allowed to change %s to read-write\n", path); |
496 | } | 502 | free(path); |
497 | 503 | return; | |
498 | // mount --bind /bin /bin | 504 | } |
499 | // mount --bind -o remount,rw /bin | 505 | // mount --bind /bin /bin |
500 | unsigned long flags = 0; | 506 | // mount --bind -o remount,rw /bin |
501 | get_mount_flags(dir, &flags); | 507 | unsigned long flags = 0; |
502 | if ((flags & MS_RDONLY) == 0) | 508 | get_mount_flags(path, &flags); |
503 | return; | 509 | if ((flags & MS_RDONLY) == 0) { |
504 | flags &= ~MS_RDONLY; | 510 | free(path); |
505 | if (mount(dir, dir, NULL, MS_BIND|MS_REC, NULL) < 0 || | 511 | return; |
506 | mount(NULL, dir, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | ||
507 | errExit("mount read-write"); | ||
508 | fs_logger2("read-write", dir); | ||
509 | } | 512 | } |
513 | flags &= ~MS_RDONLY; | ||
514 | if (mount(path, path, NULL, MS_BIND|MS_REC, NULL) < 0 || | ||
515 | mount(NULL, path, NULL, flags|MS_BIND|MS_REMOUNT|MS_REC, NULL) < 0) | ||
516 | errExit("mount read-write"); | ||
517 | fs_logger2("read-write", path); | ||
518 | |||
519 | // run a check on /proc/self/mountinfo to validate the mount | ||
520 | MountData *mptr = get_last_mount(); | ||
521 | if (strncmp(mptr->dir, path, strlen(path)) != 0) | ||
522 | errLogExit("invalid read-write mount"); | ||
523 | |||
524 | free(path); | ||
510 | } | 525 | } |
511 | 526 | ||
512 | void fs_noexec(const char *dir) { | 527 | void fs_noexec(const char *dir) { |
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c index eaaba86c0..15d44e4cc 100644 --- a/src/firejail/pulseaudio.c +++ b/src/firejail/pulseaudio.c | |||
@@ -178,10 +178,10 @@ void pulseaudio_init(void) { | |||
178 | 178 | ||
179 | // check /proc/self/mountinfo to confirm the mount is ok | 179 | // check /proc/self/mountinfo to confirm the mount is ok |
180 | MountData *mptr = get_last_mount(); | 180 | MountData *mptr = get_last_mount(); |
181 | if (strncmp(mptr->dir, homeusercfg, strlen(homeusercfg)) != 0) | 181 | if (strcmp(mptr->dir, homeusercfg) != 0) |
182 | errLogExit("invalid mount on top of %s (should be %s)\n", mptr->dir, homeusercfg); | 182 | errLogExit("invalid pulseaudio mount"); |
183 | if (strncmp(mptr->fstype, "tmpfs", 5) != 0) | 183 | if (strcmp(mptr->fstype, "tmpfs") != 0) |
184 | errLogExit("invalid mount on top of %s (filesystem type is %s)\n", mptr->dir, mptr->fstype); | 184 | errLogExit("invalid pulseaudio mount"); |
185 | 185 | ||
186 | char *p; | 186 | char *p; |
187 | if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) | 187 | if (asprintf(&p, "%s/client.conf", homeusercfg) == -1) |
diff --git a/src/firejail/x11.c b/src/firejail/x11.c index 0eace3215..ec8775370 100644 --- a/src/firejail/x11.c +++ b/src/firejail/x11.c | |||
@@ -1196,10 +1196,11 @@ void x11_xorg(void) { | |||
1196 | 1196 | ||
1197 | // check /proc/self/mountinfo to confirm the mount is ok | 1197 | // check /proc/self/mountinfo to confirm the mount is ok |
1198 | MountData *mptr = get_last_mount(); | 1198 | MountData *mptr = get_last_mount(); |
1199 | if (strncmp(mptr->dir, dest, strlen(dest)) != 0) | 1199 | if (strcmp(mptr->dir, dest) != 0) |
1200 | errLogExit("invalid mount on top of %s (should be %s)\n", mptr->dir, dest); | 1200 | errLogExit("invalid .Xauthority mount"); |
1201 | if (strncmp(mptr->fstype, "tmpfs", 5) != 0) | 1201 | if (strcmp(mptr->fstype, "tmpfs") != 0) |
1202 | errLogExit("invalid mount on top of %s (filesystem type is %s)\n", mptr->dir, mptr->fstype); | 1202 | errLogExit("invalid .Xauthority mount"); |
1203 | |||
1203 | free(dest); | 1204 | free(dest); |
1204 | #endif | 1205 | #endif |
1205 | } | 1206 | } |