Sophie

Sophie

distrib > Mageia > 1 > i586 > media > core-updates-src > by-pkgid > 9a1d5d697de4241436492d72575ac1a0 > files > 5

fuse-2.8.5-1.1.mga1.src.rpm

diff -uNr fuse-2.8.5.umount/lib/mount_util.c fuse-2.8.5/lib/mount_util.c
--- fuse-2.8.5.umount/lib/mount_util.c	2012-11-21 10:42:37.918849477 -0500
+++ fuse-2.8.5/lib/mount_util.c	2012-11-21 10:42:28.918830035 -0500
@@ -178,11 +178,7 @@
 	if (!mtab_needs_update(mnt))
 		return 0;
 
-	res = add_mount(progname, fsname, mnt, type, opts);
-	if (res == -1)
-		res = add_mount_legacy(progname, fsname, mnt, type, opts);
-
-	return res;
+	return add_mount(progname, fsname, mnt, type, opts);
 }
 
 static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
@@ -244,6 +240,56 @@
 	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 -uNr fuse-2.8.5.umount/util/fusermount.c fuse-2.8.5/util/fusermount.c
--- fuse-2.8.5.umount/util/fusermount.c	2010-09-28 04:04:13.000000000 -0400
+++ fuse-2.8.5/util/fusermount.c	2012-11-21 10:42:28.918830035 -0500
@@ -45,6 +45,16 @@
 #define MS_PRIVATE (1<<18)
 #endif
 
+#ifndef UMOUNT_DETACH
+#define UMOUNT_DETACH   0x00000002      /* Just detach from the tree */
+#endif
+#ifndef UMOUNT_NOFOLLOW
+#define UMOUNT_NOFOLLOW 0x00000008      /* Don't follow symlink on umount */
+#endif
+#ifndef UMOUNT_UNUSED
+#define UMOUNT_UNUSED   0x80000000      /* Flag guaranteed to be unused */
+#endif
+
 static const char *progname;
 
 static int user_allow_other = 0;
@@ -380,11 +390,46 @@
 	return 0;
 }
 
+static int unmount_fuse_nofollow(const char *mnt, int quiet, int lazy)
+{
+    int res;
+    int umount_flags = UMOUNT_NOFOLLOW;
+ 
+    if (lazy)
+        umount_flags |= UMOUNT_DETACH;
+ 
+    res = umount2(mnt, umount_flags);
+    if (res == -1) {
+        if (!quiet) {
+            fprintf(stderr, "%s: failed to unmount %s: %s\n",
+                progname, mnt, strerror(errno));
+        }
+        return -1;
+    }
+
+    return fuse_mnt_remove_mount(progname, mnt);
+}
+
+/* Check whether the kernel supports UMOUNT_NOFOLLOW flag */
+static int umount_nofollow_support(void)
+{
+    int res = umount2("", UMOUNT_UNUSED);
+    if (res != -1 || errno != EINVAL)
+        return 0;
+
+    res = umount2("", UMOUNT_NOFOLLOW);
+    if (res != -1 || errno != ENOENT)
+        return 0;
+
+    return 1;
+}
+
 static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
 {
 	int currdir_fd = -1;
 	char *copy;
 	const char *last;
+	int umount_flags = lazy ? UMOUNT_DETACH : 0;
 	int res;
 
 	if (getuid() != 0) {
@@ -399,24 +444,26 @@
 		return -1;
 	}
 
-	res = chdir_to_parent(copy, &last, &currdir_fd);
-	if (res == -1)
-		goto out;
-
-	res = check_is_mount(last, mnt);
-	if (res == -1)
-		goto out;
-
-	res = fuse_mnt_umount(progname, mnt, last, lazy);
+	if (umount_nofollow_support()) {
+		umount_flags |= UMOUNT_NOFOLLOW;
+	} else {
+		res = check_is_mount(last, mnt);
+		if (res == -1)
+			goto out;
+	}
+	
+	res = umount2(last, umount_flags);
+	if (res == -1 && !quiet) {
+		fprintf(stderr, "%s: failed to unmount %s: %s\n",
+			progname, mnt, strerror(errno));
+	}
 
 out:
-	free(copy);
-	if (currdir_fd != -1) {
-		fchdir(currdir_fd);
-		close(currdir_fd);
-	}
+	chdir("/");
+	if (res == -1)
+		return -1;
 
-	return res;
+	return fuse_mnt_remove_mount(progname, mnt);
 }
 
 static int unmount_fuse(const char *mnt, int quiet, int lazy)
@@ -875,7 +922,7 @@
 }
 
 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;
@@ -893,17 +940,17 @@
 		return 0;
 
 	if (S_ISDIR(stbuf->st_mode)) {
-		*currdir_fd = open(".", O_RDONLY);
-		if (*currdir_fd == -1) {
-			fprintf(stderr,
-				"%s: failed to open current directory: %s\n",
-				progname, strerror(errno));
+		*isdir = 1;
+		*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 = chdir(mnt);
+		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;
 		}
@@ -1029,6 +1076,7 @@
 	const char *real_mnt = mnt;
 	int currdir_fd = -1;
 	int mountpoint_fd = -1;
+	int isdir = 0;
 
 	fd = open_fuse_device(&dev);
 	if (fd == -1)
@@ -1048,8 +1096,7 @@
 
 	res = check_version(dev);
 	if (res != -1) {
-		res = check_perm(&real_mnt, &stbuf, &currdir_fd,
-				 &mountpoint_fd);
+		res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd, &isdir);
 		restore_privs();
 		if (res != -1)
 			res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
@@ -1058,26 +1105,38 @@
 	} else
 		restore_privs();
 
-	if (currdir_fd != -1) {
-		fchdir(currdir_fd);
-		close(currdir_fd);
-	}
+	chdir("/");
 	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, 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);
@@ -1222,6 +1281,13 @@
 
 	drop_privs();
 	mnt = fuse_mnt_resolve_path(progname, origmnt);
+	if (mnt != NULL) {
+		res = chdir("/");
+		if (res == -1) {
+			fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
+			exit(1);
+		}
+	}
 	restore_privs();
 	if (mnt == NULL)
 		exit(1);