GIT: unionfs2-2.6.27.y: cifs: Fix a kernel BUG with remote OS/2 server (try #3)

Erez Zadok ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:15:34 EDT 2010


commit dd3eae69495d9ad7a4424f38ec632e811f10a292
Author: Suresh Jayaraman <sjayaraman at suse.de>
Date:   Wed Mar 31 12:00:03 2010 +0530

    cifs: Fix a kernel BUG with remote OS/2 server (try #3)
    
    commit 6513a81e9325d712f1bfb9a1d7b750134e49ff18 upstream.
    
    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
    results in '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.
    
    The workaround is to mask off high 16 bits if the number of bytes written as
    returned by the server is greater than the bytes requested by the client as
    suggested by Jeff Layton.
    
    Reviewed-by: Jeff Layton <jlayton at samba.org>
    Signed-off-by: Suresh Jayaraman <sjayaraman at suse.de>
    Signed-off-by: Steve French <sfrench at us.ibm.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index cff0c53..31a1668 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1594,6 +1594,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
+
+		/*
+		 * Mask off high 16 bits when bytes written as returned by the
+		 * server is greater than bytes requested by the client. Some
+		 * OS/2 servers are known to set incorrect CountHigh values.
+		 */
+		if (*nbytes > count)
+			*nbytes &= 0xFFFF;
 	}
 
 	cifs_buf_release(pSMB);
@@ -1679,6 +1687,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 		*nbytes = le16_to_cpu(pSMBr->CountHigh);
 		*nbytes = (*nbytes) << 16;
 		*nbytes += le16_to_cpu(pSMBr->Count);
+
+		/*
+		 * Mask off high 16 bits when bytes written as returned by the
+		 * server is greater than bytes requested by the client. OS/2
+		 * servers are known to set incorrect CountHigh values.
+		 */
+		if (*nbytes > count)
+			*nbytes &= 0xFFFF;
 	}
 
 /*	cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */


More information about the unionfs-cvs mailing list