Sophie

Sophie

distrib > Mageia > 5 > x86_64 > media > core-updates-src > by-pkgid > e9594b11446903c9fe112a1a7136e5cb > files > 3

samba-3.6.25-2.1.mga5.src.rpm

Description: Fix a corner case of the symlink verification
 Commit 7606c0db257b3f9d84da5b2bf5fbb4034cc8d77d fixes the
 path checks in check_reduced_name[_with_privilege]() to
 prevent unintended access via wide links.
 
 The fix fails to correctly treat a corner case where the share
 path is "/". This case is important for some real world
 scenarios, notably the use of the glusterfs VFS module:
 
 For the share path "/", the newly introduced checks deny all
 operations in the share.
 
 This change fixes the checks for the corner case.
 The point is that the assumptions on which the original
 checks are based are not true for the rootdir "/" case.
 This is the case where the rootdir starts _and ends_ with
 a slash. Hence a subdirectory does not continue with a
 slash after the rootdir, since the candidate path has
 been normalized.
 .
 samba (2:3.6.3-2ubuntu2.14~lp1545750~1) precise; urgency=medium
 .
   * Fixes regression introduced by debian/patches/CVE-2015-5252.patch. (LP: #1545750)
Author: Michael Adam <obnox@samba.org>
Origin: upstream, https://git.samba.org/samba.git/?p=samba.git;a=commit;h=ada59ec7b3a5ed0478d11da2fe0c90991d137288
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1545750
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11647

--- samba-3.6.3.orig/source3/smbd/vfs.c
+++ samba-3.6.3/source3/smbd/vfs.c
@@ -982,7 +982,6 @@ NTSTATUS check_reduced_name(connection_s
 	if (!allow_widelinks || !allow_symlinks) {
 		const char *conn_rootdir;
 		size_t rootdir_len;
-		bool matched;
 
 		conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
 		if (conn_rootdir == NULL) {
@@ -993,17 +992,33 @@ NTSTATUS check_reduced_name(connection_s
 		}
 
 		rootdir_len = strlen(conn_rootdir);
-		matched = (strncmp(conn_rootdir, resolved_name,
-				rootdir_len) == 0);
-		if (!matched || (resolved_name[rootdir_len] != '/' &&
-				 resolved_name[rootdir_len] != '\0')) {
-			DEBUG(2, ("check_reduced_name: Bad access "
-				"attempt: %s is a symlink outside the "
-				"share path\n", fname));
-			DEBUGADD(2, ("conn_rootdir =%s\n", conn_rootdir));
-			DEBUGADD(2, ("resolved_name=%s\n", resolved_name));
-			SAFE_FREE(resolved_name);
-			return NT_STATUS_ACCESS_DENIED;
+
+		/*
+		 * In the case of rootdir_len == 1, we know that
+		 * conn_rootdir is "/", and we also know that
+		 * resolved_name starts with a slash.  So, in this
+		 * corner case, resolved_name is automatically a
+		 * sub-directory of the conn_rootdir. Thus we can skip
+		 * the string comparison and the next character checks
+		 * (which are even wrong in this case).
+		 */
+		if (rootdir_len != 1) {
+			bool matched;
+
+			matched = (strncmp(conn_rootdir, resolved_name,
+					rootdir_len) == 0);
+			if (!matched || (resolved_name[rootdir_len] != '/' &&
+					 resolved_name[rootdir_len] != '\0')) {
+				DEBUG(2, ("check_reduced_name: Bad access "
+					"attempt: %s is a symlink outside the "
+					"share path\n", fname));
+				DEBUGADD(2, ("conn_rootdir =%s\n",
+					     conn_rootdir));
+				DEBUGADD(2, ("resolved_name=%s\n",
+					     resolved_name));
+				SAFE_FREE(resolved_name);
+				return NT_STATUS_ACCESS_DENIED;
+			}
 		}
 
 		/* Extra checks if all symlinks are disallowed. */