aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuresh Jayaraman <sjayaraman@suse.de>2010-03-31 02:30:03 -0400
committerSteve French <sfrench@us.ibm.com>2010-04-03 13:24:20 -0400
commit6513a81e9325d712f1bfb9a1d7b750134e49ff18 (patch)
treef0f00a27d29ad6b6dc7cb05f6b10101aa01b0c64
parenta24e2d7d8f512340991ef0a59cb5d08d491b8e98 (diff)
cifs: Fix a kernel BUG with remote OS/2 server (try #3)
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. CC: Stable <stable@kernel.org> Reviewed-by: Jeff Layton <jlayton@samba.org> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cifssmb.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index e1f90a3a0162..f213b8ae43c1 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1518,6 +1518,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1518 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1518 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1519 *nbytes = (*nbytes) << 16; 1519 *nbytes = (*nbytes) << 16;
1520 *nbytes += le16_to_cpu(pSMBr->Count); 1520 *nbytes += le16_to_cpu(pSMBr->Count);
1521
1522 /*
1523 * Mask off high 16 bits when bytes written as returned by the
1524 * server is greater than bytes requested by the client. Some
1525 * OS/2 servers are known to set incorrect CountHigh values.
1526 */
1527 if (*nbytes > count)
1528 *nbytes &= 0xFFFF;
1521 } 1529 }
1522 1530
1523 cifs_buf_release(pSMB); 1531 cifs_buf_release(pSMB);
@@ -1606,6 +1614,14 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1606 *nbytes = le16_to_cpu(pSMBr->CountHigh); 1614 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1607 *nbytes = (*nbytes) << 16; 1615 *nbytes = (*nbytes) << 16;
1608 *nbytes += le16_to_cpu(pSMBr->Count); 1616 *nbytes += le16_to_cpu(pSMBr->Count);
1617
1618 /*
1619 * Mask off high 16 bits when bytes written as returned by the
1620 * server is greater than bytes requested by the client. OS/2
1621 * servers are known to set incorrect CountHigh values.
1622 */
1623 if (*nbytes > count)
1624 *nbytes &= 0xFFFF;
1609 } 1625 }
1610 1626
1611/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */ 1627/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */