Fix cleanup in case of failed mount
authorMiklos Szeredi <mszeredi@suse.cz>
Mon, 31 Jan 2011 15:32:46 +0000 (16:32 +0100)
committerMiklos Szeredi <mszeredi@suse.cz>
Mon, 31 Jan 2011 15:32:46 +0000 (16:32 +0100)
In case of failure to add to /etc/mtab use same mountpoint for cleanup
as for mounting.  Reported by Marc Deslauriers

ChangeLog
util/fusermount.c

index 768857ebae5c71e5b86bd97aa8058a628b80e5da..1eddd4c009d38ea319df0f055b26fc26dd660a64 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-31  Miklos Szeredi <miklos@szeredi.hu>
+
+       * In case of failure to add to /etc/mtab use same mountpoint for
+       cleanup as for mounting.  Reported by Marc Deslauriers
+
 2010-12-16  Miklos Szeredi <miklos@szeredi.hu>
 
        * Highlevel lib: allow hash tables to shrink
index 588d1bfb8ca4b5b77b3093b1f5a8fc2cb8d0ef38..b367c406c7d4e5d03e9196a4172122a5556c24ba 100644 (file)
@@ -1000,7 +1000,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;
@@ -1018,6 +1018,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,
@@ -1025,10 +1026,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;
                }
@@ -1154,6 +1161,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)
@@ -1174,7 +1182,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,
@@ -1188,22 +1196,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, UMOUNT_DETACH); /* lazy umount */
+                       if (isdir && mountpoint_fd != -1) {
+                               res = fchdir(mountpoint_fd);
+                               if (res == -1) {
+                                       close(mountpoint_fd);
+                                       close(fd);
+                                       return -1;
+                               }
+                       }
+                       umount2(real_mnt, UMOUNT_DETACH); /* 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);