summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2011-01-31 16:32:46 +0100
committerMiklos Szeredi <mszeredi@suse.cz>2011-01-31 17:40:49 +0100
commit77448225813fead66f8901c0462a7ea820480f84 (patch)
treef803d62ebe3152bbe3c1e18c8cad989375584e2e
parente9ae66eb4e7af14e2cd27b90f88b599b61f96e8a (diff)
downloadfuse-77448225813fead66f8901c0462a7ea820480f84.tar.gz
Fix cleanup in case of failed mount
In case of failure to add to /etc/mtab use same mountpoint for cleanup as for mounting. Reported by Marc Deslauriers
-rw-r--r--ChangeLog3
-rw-r--r--util/fusermount.c35
2 files changed, 32 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index ff1c04f..ba61398 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -7,6 +7,9 @@
* Always call mount with --no-canonicalize option to prevent
symlink attacks on mount.
+ * In case of failure to add to /etc/mtab use same mountpoint for
+ cleanup as for mounting. Reported by Marc Deslauriers
+
2010-11-08 Miklos Szeredi <miklos@szeredi.hu>
* Open /dev/null for write instead of read for redirecting stdout
diff --git a/util/fusermount.c b/util/fusermount.c
index 731f56d..70c18b7 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -882,7 +882,7 @@ static int check_version(const char *dev)
}
static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
- int *mountpoint_fd)
+ int *mountpoint_fd, int *isdir)
{
int res;
const char *mnt = *mntp;
@@ -900,6 +900,7 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
return 0;
if (S_ISDIR(stbuf->st_mode)) {
+ *isdir = 1;
*currdir_fd = open(".", O_RDONLY);
if (*currdir_fd == -1) {
fprintf(stderr,
@@ -907,10 +908,16 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd,
progname, strerror(errno));
return -1;
}
- res = chdir(mnt);
+ *mountpoint_fd = open(mnt, O_RDONLY);
+ if (*mountpoint_fd == -1) {
+ fprintf(stderr, "%s: failed to open %s: %s\n",
+ progname, mnt, strerror(errno));
+ return -1;
+ }
+ res = fchdir(*mountpoint_fd);
if (res == -1) {
fprintf(stderr,
- "%s: failed to chdir to mountpoint: %s\n",
+ "%s: failed to fchdir to mountpoint: %s\n",
progname, strerror(errno));
return -1;
}
@@ -1036,6 +1043,7 @@ static int mount_fuse(const char *mnt, const char *opts)
const char *real_mnt = mnt;
int currdir_fd = -1;
int mountpoint_fd = -1;
+ int isdir = 0;
fd = open_fuse_device(&dev);
if (fd == -1)
@@ -1056,7 +1064,7 @@ static int mount_fuse(const char *mnt, const char *opts)
res = check_version(dev);
if (res != -1) {
res = check_perm(&real_mnt, &stbuf, &currdir_fd,
- &mountpoint_fd);
+ &mountpoint_fd, &isdir);
restore_privs();
if (res != -1)
res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
@@ -1070,22 +1078,37 @@ static int mount_fuse(const char *mnt, const char *opts)
close(currdir_fd);
}
if (mountpoint_fd != -1)
- close(mountpoint_fd);
+ fcntl(mountpoint_fd, F_SETFD, FD_CLOEXEC);
if (res == -1) {
close(fd);
+ if (mountpoint_fd != -1)
+ close(mountpoint_fd);
return -1;
}
if (geteuid() == 0) {
res = add_mount(source, mnt, type, mnt_opts);
if (res == -1) {
- umount2(mnt, 2); /* lazy umount */
+ if (isdir && mountpoint_fd != -1) {
+ res = fchdir(mountpoint_fd);
+ if (res == -1) {
+ close(mountpoint_fd);
+ close(fd);
+ return -1;
+ }
+ }
+ umount2(real_mnt, 2); /* lazy umount */
+ if (mountpoint_fd != -1)
+ close(mountpoint_fd);
close(fd);
return -1;
}
}
+ if (mountpoint_fd != -1)
+ close(mountpoint_fd);
+
free(source);
free(type);
free(mnt_opts);