kernel/cifs-sanity-check-length-of...

130 lines
5.6 KiB
Diff

Path: news.gmane.org!not-for-mail
From: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Newsgroups: gmane.linux.kernel.cifs
Subject: [PATCH] cifs: sanity check length of data to send before sending
Date: Fri, 14 Feb 2014 07:21:00 -0500
Lines: 72
Approved: news@gmane.org
Message-ID: <1392380460-6997-1-git-send-email-jlayton@redhat.com>
NNTP-Posting-Host: plane.gmane.org
X-Trace: ger.gmane.org 1392380460 7637 80.91.229.3 (14 Feb 2014 12:21:00 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Fri, 14 Feb 2014 12:21:00 +0000 (UTC)
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
To: smfrench-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
Original-X-From: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Fri Feb 14 13:21:08 2014
Return-path: <linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Envelope-to: glkc-linux-cifs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org
Original-Received: from vger.kernel.org ([209.132.180.67])
by plane.gmane.org with esmtp (Exim 4.69)
(envelope-from <linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>)
id 1WEHlT-0001gj-Pf
for glkc-linux-cifs-wOFGN7rlS/M9smdsby/KFg@public.gmane.org; Fri, 14 Feb 2014 13:21:08 +0100
Original-Received: (majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org) by vger.kernel.org via listexpand
id S1751935AbaBNMVH (ORCPT <rfc822;glkc-linux-cifs@m.gmane.org>);
Fri, 14 Feb 2014 07:21:07 -0500
Original-Received: from mail-qc0-f170.google.com ([209.85.216.170]:60206 "EHLO
mail-qc0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S1751288AbaBNMVG (ORCPT
<rfc822;linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>); Fri, 14 Feb 2014 07:21:06 -0500
Original-Received: by mail-qc0-f170.google.com with SMTP id e9so20306487qcy.29
for <linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; Fri, 14 Feb 2014 04:21:05 -0800 (PST)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20130820;
h=x-gm-message-state:sender:from:to:cc:subject:date:message-id;
bh=8FvTfO9jKY+Fzw5nmoxw6PuPxfXM/khvtS/Hnxnu+to=;
b=i7Gy5AwQiFX7hVMJJMjvAR61u2zO8E7tTAgE0SfPp25untipj/RTae8xcA+0vVrznY
sZwOPATUyFmu2mXAKh5L0WutFNF3SQirPVgM5jaKlMZQT253YInioO1AwD00Jtio00LX
wOt19I6v3umZfSqCBw1dyDiH66kX4xKaKqdQoY2+nEsicG4RJvp4PpaLhG454nfpVxfN
HeskcNJ5RBvg17JpDvKX6THqbKWsHSHHqKKCROERxeTbs7HTgV9jTNSDeOuPr6Loiovi
9DBQwQwMmlC9NebDqR5xatva30WRhyCp/xyHNaoY+aVk8N6r5YlFphLmLRvmaZ0Ed2CH
17WA==
X-Gm-Message-State: ALoCoQmHyaepi0IHvwKS024wRq/srAdGRdo0UGUynLggzf843S3Yj7dwW53RjNbTDG1Y4w+/mqOB
X-Received: by 10.229.13.133 with SMTP id c5mr12315963qca.22.1392380465000;
Fri, 14 Feb 2014 04:21:05 -0800 (PST)
Original-Received: from tlielax.poochiereds.net ([2001:470:8:d63:3a60:77ff:fe93:a95d])
by mx.google.com with ESMTPSA id u4sm15047497qai.21.2014.02.14.04.21.04
for <multiple recipients>
(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
Fri, 14 Feb 2014 04:21:04 -0800 (PST)
X-Mailer: git-send-email 1.8.5.3
Original-Sender: linux-cifs-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Precedence: bulk
List-ID: <linux-cifs.vger.kernel.org>
X-Mailing-List: linux-cifs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Xref: news.gmane.org gmane.linux.kernel.cifs:9402
Archived-At: <http://permalink.gmane.org/gmane.linux.kernel.cifs/9402>
We had a bug discovered recently where an upper layer function
(cifs_iovec_write) could pass down a smb_rqst with an invalid amount of
data in it. The length of the SMB frame would be correct, but the rqst
struct would cause smb_send_rqst to send nearly 4GB of data.
This should never be the case. Add some sanity checking to the beginning
of smb_send_rqst that ensures that the amount of data we're going to
send agrees with the length in the RFC1002 header. If it doesn't, WARN()
and return -EIO to the upper layers.
Signed-off-by: Jeff Layton <jlayton-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
fs/cifs/transport.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index b37570952846..18cd5650a5fc 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -270,6 +270,26 @@ cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
iov->iov_len = rqst->rq_pagesz;
}
+static unsigned long
+rqst_len(struct smb_rqst *rqst)
+{
+ unsigned int i;
+ struct kvec *iov = rqst->rq_iov;
+ unsigned long buflen = 0;
+
+ /* total up iov array first */
+ for (i = 0; i < rqst->rq_nvec; i++)
+ buflen += iov[i].iov_len;
+
+ /* add in the page array if there is one */
+ if (rqst->rq_npages) {
+ buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
+ buflen += rqst->rq_tailsz;
+ }
+
+ return buflen;
+}
+
static int
smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
{
@@ -277,6 +297,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
struct kvec *iov = rqst->rq_iov;
int n_vec = rqst->rq_nvec;
unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
+ unsigned long send_length;
unsigned int i;
size_t total_len = 0, sent;
struct socket *ssocket = server->ssocket;
@@ -285,6 +306,14 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
if (ssocket == NULL)
return -ENOTSOCK;
+ /* sanity check send length */
+ send_length = rqst_len(rqst);
+ if (send_length != smb_buf_length + 4) {
+ WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
+ send_length, smb_buf_length);
+ return -EIO;
+ }
+
cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
dump_smb(iov[0].iov_base, iov[0].iov_len);
--
1.8.5.3