[hardy CVE 1/1] cifs: ensure we check both username and password when reusing a session

Andy Whitcroft apw at canonical.com
Tue Oct 25 16:12:22 UTC 2011


In the case where we do match by username, we also need to match by
password.  That ensures that someone else doesn't "borrow" an existing
session without needing to know the password.

Also now that we may not reuse the connection ensure we do not force
disconnect any existing connection.

Equivalent to the CVE components of:
  commit 4ff67b720c02c36e54d55b88c2931879b7db1cd2
  commit fc87a40677bbe0937e2ff0642c7e83c9a4813f3d
  commit 24e6cf92fde1f140d8eb0bf7cd24c2c78149b6b2

CVE-2011-1585
BugLink: http://bugs.launchpad.net/bugs/869208
Signed-off-by: Andy Whitcroft <apw at canonical.com>
---
 fs/cifs/connect.c |   36 +++++++++++++++++++++++++++++-------
 1 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 6eb27ff..f31f906 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1316,10 +1316,34 @@ cifs_parse_mount_options(char *options, const char *devname,
 	return 0;
 }
 
+int __username_password_chk(struct cifsSesInfo *ses, struct smb_vol *vol)
+{
+	struct TCP_Server_Info *server = ses->server;
+
+	switch (server->secType) {
+	case Kerberos:
+		if (vol->linux_uid != ses->linux_uid)
+			return 0;
+		break;
+	default:
+		/* anything else takes username/password */
+		if (strncmp(ses->userName, vol->username,
+			    MAX_USERNAME_SIZE))
+			return 0;
+		if (strlen(vol->username) != 0 &&
+		    ses->password != NULL &&
+		    strncmp(ses->password,
+			    vol->password ? vol->password : "",
+			    MAX_PASSWORD_SIZE))
+			return 0;
+	}
+	return 1;
+}
+
 static struct cifsSesInfo *
 cifs_find_tcp_session(struct in_addr *target_ip_addr,
 		struct in6_addr *target_ip6_addr,
-		 char *userName, struct TCP_Server_Info **psrvTcp)
+		struct smb_vol *vol, struct TCP_Server_Info **psrvTcp)
 {
 	struct list_head *tmp;
 	struct cifsSesInfo *ses;
@@ -1341,9 +1365,7 @@ cifs_find_tcp_session(struct in_addr *target_ip_addr,
 				*psrvTcp = ses->server;
 
 				/* BB check if reconnection needed */
-				if (strncmp
-				    (ses->userName, userName,
-				     MAX_USERNAME_SIZE) == 0){
+				if (__username_password_chk(ses, vol)) {
 					read_unlock(&GlobalSMBSeslock);
 					/* Found exact match on both TCP and
 					   SMB sessions */
@@ -1882,12 +1904,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 	if (address_type == AF_INET)
 		existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
 			NULL /* no ipv6 addr */,
-			volume_info.username, &srvTcp);
+			&volume_info, &srvTcp);
 	else if (address_type == AF_INET6) {
 		cFYI(1, ("looking for ipv6 address"));
 		existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
 			&sin_server6.sin6_addr,
-			volume_info.username, &srvTcp);
+			&volume_info, &srvTcp);
 	} else {
 		rc = -EINVAL;
 		goto out;
@@ -2178,7 +2200,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 						if (tsk)
 							kthread_stop(tsk);
 					}
-				} else {
+				} else if (atomic_read(&srvTcp->socketUseCount) == 0) {
 					cFYI(1, ("No session or bad tcon"));
 					if ((pSesInfo->server) &&
 					    (pSesInfo->server->tsk)) {
-- 
1.7.5.4




More information about the kernel-team mailing list