From patchwork Tue Oct 25 16:12:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Whitcroft X-Patchwork-Id: 121733 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 8623B1007E3 for ; Wed, 26 Oct 2011 03:12:44 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1RIjc8-0000dE-Lq; Tue, 25 Oct 2011 16:12:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1RIjc6-0000cP-KO for kernel-team@lists.ubuntu.com; Tue, 25 Oct 2011 16:12:30 +0000 Received: from 212-139-208-147.dynamic.dsl.as9105.com ([212.139.208.147] helo=localhost.localdomain) by youngberry.canonical.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1RIjc6-0004JJ-EI; Tue, 25 Oct 2011 16:12:30 +0000 From: Andy Whitcroft To: kernel-team@lists.ubuntu.com Subject: [hardy CVE 1/1] cifs: ensure we check both username and password when reusing a session Date: Tue, 25 Oct 2011 17:12:22 +0100 Message-Id: <1319559148-30401-2-git-send-email-apw@canonical.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1319559148-30401-1-git-send-email-apw@canonical.com> References: <1319559148-30401-1-git-send-email-apw@canonical.com> Cc: Andy Whitcroft X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com 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 --- 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)) {