Sophie

Sophie

distrib > Mageia > 1 > i586 > by-pkgid > 06f7bfb68c26fb4465e5af609592abd4 > files > 2

cifs-utils-4.8.1-1.3.mga1.src.rpm

diff -up cifs-utils-4.8.1/configure.ac.cve-2012-1586 cifs-utils-4.8.1/configure.ac
--- cifs-utils-4.8.1/configure.ac.cve-2012-1586	2011-01-21 20:55:25.000000000 +0200
+++ cifs-utils-4.8.1/configure.ac	2012-05-05 18:34:05.000000000 +0200
@@ -30,6 +30,10 @@ AC_GNU_SOURCE
 # Checks for header files.
 AC_CHECK_HEADERS([arpa/inet.h ctype.h fcntl.h inttypes.h limits.h mntent.h netdb.h stddef.h stdint.h stdlib.h string.h strings.h sys/mount.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h], , [AC_MSG_ERROR([necessary header(s) not found])])
 
+# do we have sys/fsuid.h and setfsuid()?
+AC_CHECK_HEADERS([sys/fsuid.h])
+AC_CHECK_FUNC(setfsuid, , [AC_MSG_ERROR([System does not support setfsuid()])])
+
 if test $enable_cifsupcall != "no"; then
 	AC_CHECK_HEADERS([krb5.h krb5/krb5.h])
 	if test x$ac_cv_header_krb5_krb5_h != xyes ; then
diff -up cifs-utils-4.8.1/mount.cifs.8.cve-2012-1586 cifs-utils-4.8.1/mount.cifs.8
--- cifs-utils-4.8.1/mount.cifs.8.cve-2012-1586	2011-01-21 20:55:25.000000000 +0200
+++ cifs-utils-4.8.1/mount.cifs.8	2012-05-05 18:34:05.000000000 +0200
@@ -470,7 +470,8 @@ The variable
 may contain the pathname of a file to read the password from\&. A single line of input is read and used as the password\&.
 .SH "NOTES"
 .PP
-This command may be used only by root, unless installed setuid, in which case the noeexec and nosuid mount flags are enabled\&. When installed as a setuid program, the program follows the conventions set forth by the mount program for user mounts\&.
+This command may be used only by root, unless installed setuid, in which case the noeexec and nosuid mount flags are enabled\&. When installed as a setuid program, the program follows the conventions set forth by the mount program for user mounts, with the added restriction that users must be able to chdir() into the
+mountpoint prior to the mount in order to be able to mount onto it.
 .PP
 Some samba client tools like smbclient(8) honour client\-side configuration parameters present in smb\&.conf\&. Unlike those client tools,
 \fImount\&.cifs\fR
diff -up cifs-utils-4.8.1/mount.cifs.c.cve-2012-1586 cifs-utils-4.8.1/mount.cifs.c
--- cifs-utils-4.8.1/mount.cifs.c.cve-2012-1586	2012-05-05 18:33:58.000000000 +0200
+++ cifs-utils-4.8.1/mount.cifs.c	2012-05-05 18:34:05.000000000 +0200
@@ -44,6 +44,9 @@
 #include <paths.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
+#ifdef HAVE_SYS_FSUID_H
+#include <sys/fsuid.h>
+#endif /* HAVE_SYS_FSUID_H */
 #ifdef HAVE_LIBCAP_NG
 #include <cap-ng.h>
 #else /* HAVE_LIBCAP_NG */
@@ -1692,6 +1695,68 @@ assemble_exit:
 	return rc;
 }
 
+/*
+ * chdir() into the mountpoint and determine "realpath". We assume here that
+ * "mountpoint" is a statically allocated string and does not need to be freed.
+ */
+static int
+acquire_mountpoint(char **mountpointp)
+{
+	int rc, dacrc;
+	uid_t realuid, oldfsuid;
+	gid_t oldfsgid;
+	char *mountpoint;
+
+	/*
+	 * Acquire the necessary privileges to chdir to the mountpoint. If
+	 * the real uid is root, then we reacquire CAP_DAC_READ_SEARCH. If
+	 * it's not, then we change the fsuid to the real uid to ensure that
+	 * the mounting user actually has access to the mountpoint.
+	 *
+	 * The mount(8) manpage does not state that users must be able to
+	 * chdir into the mountpoint in order to mount onto it, but if we
+	 * allow that, then an unprivileged user could use this program to
+	 * "probe" into directories to which he does not have access.
+	 */
+	realuid = getuid();
+	if (realuid == 0) {
+		dacrc = toggle_dac_capability(0, 1);
+		if (dacrc)
+			return dacrc;
+	} else {
+		oldfsuid = setfsuid(realuid);
+		oldfsgid = setfsgid(getgid());
+	}
+
+	rc = chdir(*mountpointp);
+	if (rc) {
+		fprintf(stderr, "Couldn't chdir to %s: %s\n", *mountpointp,
+			strerror(errno));
+		rc = EX_USAGE;
+		goto restore_privs;
+	}
+
+	mountpoint = realpath(".", NULL);
+	if (!mountpoint) {
+		fprintf(stderr, "Unable to resolve %s to canonical path: %s\n",
+			*mountpointp, strerror(errno));
+		rc = EX_SYSERR;
+	}
+
+	*mountpointp = mountpoint;
+restore_privs:
+	if (realuid == 0) {
+		dacrc = toggle_dac_capability(0, 0);
+		if (dacrc)
+			rc = rc ? rc : dacrc;
+	} else {
+		setfsuid(oldfsuid);
+		setfsgid(oldfsgid);
+	}
+
+	return rc;
+}
+
 int main(int argc, char **argv)
 {
 	int c;
@@ -1788,25 +1853,7 @@ int main(int argc, char **argv)
 	mountpoint = argv[optind + 1];
 
 	/* chdir into mountpoint as soon as possible */
-	rc = toggle_dac_capability(0, 1);
-	if (rc)
-		return rc;
-	rc = chdir(mountpoint);
-	if (rc) {
-		fprintf(stderr, "Couldn't chdir to %s: %s\n", mountpoint,
-			strerror(errno));
-		rc = EX_USAGE;
-		goto mount_exit;
-	}
-
-	mountpoint = realpath(".", NULL);
-	if (!mountpoint) {
-		fprintf(stderr, "Unable to resolve %s to canonical path: %s\n",
-			mountpoint, strerror(errno));
-		rc = EX_SYSERR;
-		goto mount_exit;
-	}
-	rc = toggle_dac_capability(0, 0);
+	rc = acquire_mountpoint(&mountpoint);
 	if (rc)
 		return rc;