From patchwork Tue Mar 30 08:47:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suresh Jayaraman X-Patchwork-Id: 48945 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.samba.org (fn.samba.org [216.83.154.106]) by ozlabs.org (Postfix) with ESMTP id B7ADEB7C67 for ; Tue, 30 Mar 2010 20:08:18 +1100 (EST) Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id B119AAD16A; Tue, 30 Mar 2010 03:08:20 -0600 (MDT) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on fn.samba.org X-Spam-Level: X-Spam-Status: No, score=-4.7 required=3.8 tests=AWL,BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org X-Greylist: delayed 1219 seconds by postgrey-1.32 at fn.samba.org; Tue, 30 Mar 2010 03:08:14 MDT Received: from victor.provo.novell.com (victor.provo.novell.com [137.65.250.26]) by lists.samba.org (Postfix) with ESMTP id 1D425AD158 for ; Tue, 30 Mar 2010 03:08:13 -0600 (MDT) Received: from localhost (prv-ext-foundry1int.gns.novell.com [137.65.251.240]) by victor.provo.novell.com with ESMTP; Tue, 30 Mar 2010 02:47:48 -0600 From: Suresh Jayaraman To: Steve French Date: Tue, 30 Mar 2010 14:17:43 +0530 Message-Id: <1269938863-13779-1-git-send-email-sjayaraman@suse.de> X-Mailer: git-send-email 1.6.4.2 Cc: linux-cifs-client@lists.samba.org Subject: [linux-cifs-client] [PATCH] cifs: Fix a kernel BUG with remote OS/2 server X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org While chasing a bug report involving a OS/2 server, I noticed the server sets pSMBr->CountHigh to a incorrect value even in case of normal writes. This leads to 'nbytes' being computed wrongly and triggers a kernel BUG at mm/filemap.c. void iov_iter_advance(struct iov_iter *i, size_t bytes) { BUG_ON(i->count < bytes); <--- BUG here Why the server is setting 'CountHigh' is not clear but only does so after writing 64k bytes. Though this looks like the server bug, the client side crash may not be acceptable. Looking up the CIFS spec, the purpose of 'CountHigh' field in WriteAndX response is not clear. But since 'nbytes' can be greater than 64k only in case of large writes (default writes can be upto 56k), I assume 'CountHigh' is used only for larger writes. The below patch workarounds the case when servers set 'CountHigh' incorrectly for normal writes. Signed-off-by: Suresh Jayaraman --- fs/cifs/cifssmb.c | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7cc7f83..ceced62 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1514,8 +1514,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, cFYI(1, ("Send error in write = %d", rc)); *nbytes = 0; } else { - *nbytes = le16_to_cpu(pSMBr->CountHigh); - *nbytes = (*nbytes) << 16; + /* + * Some legacy servers (read OS/2) might incorrectly set + * CountHigh for normal writes resulting in wrong 'nbytes' value + */ + if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) { + *nbytes = le16_to_cpu(pSMBr->CountHigh); + *nbytes = (*nbytes) << 16; + } *nbytes += le16_to_cpu(pSMBr->Count); } @@ -1602,8 +1608,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, rc = -EIO; } else { WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base; - *nbytes = le16_to_cpu(pSMBr->CountHigh); - *nbytes = (*nbytes) << 16; + /* + * Some legacy servers (read OS/2) might incorrectly set + * CountHigh for normal writes resulting in wrong 'nbytes' value + */ + if (tcon->ses->capabilities & CAP_LARGE_WRITE_X) { + *nbytes = le16_to_cpu(pSMBr->CountHigh); + *nbytes = (*nbytes) << 16; + } *nbytes += le16_to_cpu(pSMBr->Count); }