xorl %eax, %eax

CVE-2011-1585: Linux kernel CIFS Session Reuse

leave a comment »

This is an old issue reported by Jeff Layton of Red Hat. As an overview we can read the oss-security email that defines it as:

When one user has mounted a cifs share that requires authentication,
another user could mount the same share without knowing the
correct password.

This was fixed by a series of patches starting in 07 July 2010 as we can find here. This one updated fs/cifs/cifsglob.h header file in order to be able to handle passwords with size greater than 16 characters long.

-#define MAX_PASSWORD_SIZE 16
+#define MAX_PASSWORD_SIZE 512  /* max for windows seems to be 256 wide chars */

Furthermore, fs/cifs/connect.c was changed and more specifically, the cifs_find_smb_ses() routine was patched in order to include a special case for Kerberos authentication. You can see the patch here:

 static struct cifsSesInfo *
-cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
+cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
 {
-	struct list_head *tmp;
 	struct cifsSesInfo *ses;
 
 	write_lock(&cifs_tcp_ses_lock);
-	list_for_each(tmp, &server->smb_ses_list) {
-		ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
-		if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
-			continue;
-
+	list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+		switch (server->secType) {
+		case Kerberos:
+			if (vol->linux_uid != ses->linux_uid)
+				continue;
+			break;
+		default:
+			/* anything else takes username/password */
+			if (strncmp(ses->userName, vol->username,
+				    MAX_USERNAME_SIZE))
+				continue;
+			if (strlen(vol->username) != 0 &&
+			    strncmp(ses->password, vol->password,
+				    MAX_PASSWORD_SIZE))
+				continue;
+		}
 		++ses->ses_count;

As you can see, the latter function will not take directly the username as an argument but instead it will take the equivalent CIFS volume structure. If the authentication scheme uses Kerberos it will ignore any UID mismatches and in any other case it will proceed to a simple strncmp() based check for the username and password.

The next patch regarding this issue was committed on 18 August 2010 and fixes a possible NULL pointer dereference since the ‘vol->password’ is initialized only if explicitely passed via the options string. The fix was as simple as this:

 			if (strlen(vol->username) != 0 &&
-			    strncmp(ses->password, vol->password,
+			    strncmp(ses->password,
+				    vol->password ? vol->password : "",
 				    MAX_PASSWORD_SIZE))
 				continue;

Finally, on 23 August 2010 Jeff Layton noticed that it is possible to have NULL password so he included this check in the default authentication scheme.

 			if (strlen(vol->username) != 0 &&
+			    ses->password != NULL &&
 			    strncmp(ses->password,
 				    vol->password ? vol->password : "",
 				    MAX_PASSWORD_SIZE))

Written by xorl

May 2, 2011 at 21:02

Posted in bugs, linux

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s