diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2010-01-26 18:20:13 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2010-01-26 18:20:13 +0000 |
commit | 8b3a0c74a15e237eb4b7053774600f0ce3fff403 (patch) | |
tree | 9de3b1b3a5110c94449bc794565bd1aedb1e4c86 /lib | |
parent | d29bc735ad9d10ca2d71e772d432983c8618fb26 (diff) |
* Fix race if two "fusermount -u" instances are run in parallel.
Reported by Dan Rosenberg
* Make sure that the path to be unmounted doesn't refer to a
symlink
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mount.c | 2 | ||||
-rw-r--r-- | lib/mount_util.c | 31 | ||||
-rw-r--r-- | lib/mount_util.h | 3 |
3 files changed, 20 insertions, 16 deletions
diff --git a/lib/mount.c b/lib/mount.c index 941644f..c3b16a4 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -290,7 +290,7 @@ void fuse_kern_unmount(const char *mountpoint, int fd) } if (geteuid() == 0) { - fuse_mnt_umount("fuse", mountpoint, 1); + fuse_mnt_umount("fuse", mountpoint, mountpoint, 1); return; } diff --git a/lib/mount_util.c b/lib/mount_util.c index 3b6e771..e18e7a4 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -184,13 +184,13 @@ int fuse_mnt_add_mount(const char *progname, const char *fsname, return res; } -static int exec_umount(const char *progname, const char *mnt, int lazy, - int legacy) +static int exec_umount(const char *progname, const char *rel_mnt, int lazy) { int res; int status; sigset_t blockmask; sigset_t oldmask; + int legacy = 0; sigemptyset(&blockmask); sigaddset(&blockmask, SIGCHLD); @@ -200,6 +200,7 @@ static int exec_umount(const char *progname, const char *mnt, int lazy, return -1; } +retry_umount: res = fork(); if (res == -1) { fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno)); @@ -219,11 +220,11 @@ static int exec_umount(const char *progname, const char *mnt, int lazy, sigprocmask(SIG_SETMASK, &oldmask, NULL); setuid(geteuid()); if (legacy) { - execl("/bin/umount", "/bin/umount", "-i", mnt, + execl("/bin/umount", "/bin/umount", "-i", rel_mnt, lazy ? "-l" : NULL, NULL); } else { execl("/bin/umount", "/bin/umount", "--no-canonicalize", - "-i", mnt, lazy ? "-l" : NULL, NULL); + "-i", rel_mnt, lazy ? "-l" : NULL, NULL); } fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname, strerror(errno)); @@ -233,8 +234,13 @@ static int exec_umount(const char *progname, const char *mnt, int lazy, if (res == -1) fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno)); - if (status != 0) + if (status != 0) { + if (!legacy) { + legacy = 1; + goto retry_umount; + } res = -1; + } out_restore: sigprocmask(SIG_SETMASK, &oldmask, NULL); @@ -242,23 +248,20 @@ static int exec_umount(const char *progname, const char *mnt, int lazy, } -int fuse_mnt_umount(const char *progname, const char *mnt, int lazy) +int fuse_mnt_umount(const char *progname, const char *abs_mnt, + const char *rel_mnt, int lazy) { int res; - if (!mtab_needs_update(mnt)) { - res = umount2(mnt, lazy ? 2 : 0); + if (!mtab_needs_update(abs_mnt)) { + res = umount2(rel_mnt, lazy ? 2 : 0); if (res == -1) fprintf(stderr, "%s: failed to unmount %s: %s\n", - progname, mnt, strerror(errno)); + progname, abs_mnt, strerror(errno)); return res; } - res = exec_umount(progname, mnt, lazy, 0); - if (res == -1) - res = exec_umount(progname, mnt, lazy, 1); - - return res; + return exec_umount(progname, rel_mnt, lazy); } char *fuse_mnt_resolve_path(const char *progname, const char *orig) diff --git a/lib/mount_util.h b/lib/mount_util.h index cf54d9d..f392f99 100644 --- a/lib/mount_util.h +++ b/lib/mount_util.h @@ -10,7 +10,8 @@ int fuse_mnt_add_mount(const char *progname, const char *fsname, const char *mnt, const char *type, const char *opts); -int fuse_mnt_umount(const char *progname, const char *mnt, int lazy); +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); int fuse_mnt_check_empty(const char *progname, const char *mnt, mode_t rootmode, off_t rootsize); |