summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-01-31 17:40:49 +0100
committerMiklos Szeredi <mszeredi@suse.cz>2011-01-31 17:40:49 +0100
commitea8d5594b1432589ba286e4501c5f6dcba3d8dab (patch)
tree429da4850304e51077d1586c7888ba14fa59c941
parentccb671bca8919f7c93fe703ee981e70f1dbcdd8e (diff)
downloadfuse-ea8d5594b1432589ba286e4501c5f6dcba3d8dab.tar.gz
Always call umount with --no-canonicalize --fake options
Always call umount with --no-canonicalize --fake options to prevent symlink attacks at umount. util-linux >= 2.18 or a suitably patched version is required.
-rw-r--r--ChangeLog6
-rw-r--r--lib/mount_util.c49
-rw-r--r--lib/mount_util.h1
-rw-r--r--util/fusermount.c9
4 files changed, 64 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index fb3504b..49f4e71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-01-31 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Always call umount with --no-canonicalize --fake options to
+ prevent symlink attacks at umount. util-linux >= 2.18 or a
+ suitably patched version is required.
+
2010-11-08 Miklos Szeredi <miklos@szeredi.hu>
* Open /dev/null for write instead of read for redirecting stdout
diff --git a/lib/mount_util.c b/lib/mount_util.c
index 5469c1b..4230e63 100644
--- a/lib/mount_util.c
+++ b/lib/mount_util.c
@@ -243,6 +243,55 @@ int fuse_mnt_umount(const char *progname, const char *abs_mnt,
return exec_umount(progname, rel_mnt, lazy);
}
+static int remove_mount(const char *progname, const char *mnt)
+{
+ int res;
+ int status;
+ sigset_t blockmask;
+ sigset_t oldmask;
+
+ sigemptyset(&blockmask);
+ sigaddset(&blockmask, SIGCHLD);
+ res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
+ if (res == -1) {
+ fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
+ return -1;
+ }
+
+ res = fork();
+ if (res == -1) {
+ fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
+ goto out_restore;
+ }
+ if (res == 0) {
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ setuid(geteuid());
+ execl("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
+ "--fake", mnt, NULL);
+ fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
+ progname, strerror(errno));
+ exit(1);
+ }
+ res = waitpid(res, &status, 0);
+ if (res == -1)
+ fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
+
+ if (status != 0)
+ res = -1;
+
+ out_restore:
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ return res;
+}
+
+int fuse_mnt_remove_mount(const char *progname, const char *mnt)
+{
+ if (!mtab_needs_update(mnt))
+ return 0;
+
+ return remove_mount(progname, mnt);
+}
+
char *fuse_mnt_resolve_path(const char *progname, const char *orig)
{
char buf[PATH_MAX];
diff --git a/lib/mount_util.h b/lib/mount_util.h
index f392f99..dc5c916 100644
--- a/lib/mount_util.h
+++ b/lib/mount_util.h
@@ -10,6 +10,7 @@
int fuse_mnt_add_mount(const char *progname, const char *fsname,
const char *mnt, const char *type, const char *opts);
+int fuse_mnt_remove_mount(const char *progname, const char *mnt);
int fuse_mnt_umount(const char *progname, const char *abs_mnt,
const char *rel_mnt, int lazy);
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
diff --git a/util/fusermount.c b/util/fusermount.c
index 39da9b6..731f56d 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -407,8 +407,15 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
if (res == -1)
goto out;
- res = fuse_mnt_umount(progname, mnt, last, lazy);
+ res = umount2(last, lazy ? 2 : 0);
+ if (res == -1 && !quiet) {
+ fprintf(stderr,
+ "%s: failed to unmount %s: %s\n",
+ progname, mnt, strerror(errno));
+ }
+ if (res == 0)
+ res = fuse_mnt_remove_mount(progname, mnt);
out:
free(copy);
if (currdir_fd != -1) {