aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsglob.h12
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c58
-rw-r--r--fs/cifs/connect.c12
-rw-r--r--fs/cifs/netmisc.c3
5 files changed, 53 insertions, 34 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 34a897e3d225..a40339826178 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -341,6 +341,18 @@ has_credits(struct TCP_Server_Info *server, int *credits)
341 return num > 0; 341 return num > 0;
342} 342}
343 343
344static inline size_t
345header_size(void)
346{
347 return sizeof(struct smb_hdr);
348}
349
350static inline size_t
351max_header_size(void)
352{
353 return MAX_CIFS_HDR_SIZE;
354}
355
344/* 356/*
345 * Macros to allow the TCP_Server_Info->net field and related code to drop out 357 * Macros to allow the TCP_Server_Info->net field and related code to drop out
346 * when CONFIG_NET_NS isn't set. 358 * when CONFIG_NET_NS isn't set.
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 70124ae77aa8..05f0a2e7e14a 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -106,7 +106,7 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
106extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); 106extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
107extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, 107extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
108 const unsigned short int port); 108 const unsigned short int port);
109extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr); 109extern int map_smb_to_linux_error(char *buf, bool logErr);
110extern void header_assemble(struct smb_hdr *, char /* command */ , 110extern void header_assemble(struct smb_hdr *, char /* command */ ,
111 const struct cifs_tcon *, int /* length of 111 const struct cifs_tcon *, int /* length of
112 fixed section (word count) in two byte units */); 112 fixed section (word count) in two byte units */);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index a7ed01cd0242..c45d445e2094 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1414,8 +1414,7 @@ cifs_readdata_free(struct cifs_readdata *rdata)
1414static int 1414static int
1415cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1415cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1416{ 1416{
1417 READ_RSP *rsp = (READ_RSP *)server->smallbuf; 1417 unsigned int rfclen = get_rfc1002_length(server->smallbuf);
1418 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length);
1419 int remaining = rfclen + 4 - server->total_read; 1418 int remaining = rfclen + 4 - server->total_read;
1420 struct cifs_readdata *rdata = mid->callback_data; 1419 struct cifs_readdata *rdata = mid->callback_data;
1421 1420
@@ -1424,7 +1423,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1424 1423
1425 length = cifs_read_from_socket(server, server->bigbuf, 1424 length = cifs_read_from_socket(server, server->bigbuf,
1426 min_t(unsigned int, remaining, 1425 min_t(unsigned int, remaining,
1427 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)); 1426 CIFSMaxBufSize + max_header_size()));
1428 if (length < 0) 1427 if (length < 0)
1429 return length; 1428 return length;
1430 server->total_read += length; 1429 server->total_read += length;
@@ -1435,14 +1434,35 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1435 return 0; 1434 return 0;
1436} 1435}
1437 1436
1437static inline size_t
1438read_rsp_size(void)
1439{
1440 return sizeof(READ_RSP);
1441}
1442
1443static inline unsigned int
1444read_data_offset(char *buf)
1445{
1446 READ_RSP *rsp = (READ_RSP *)buf;
1447 return le16_to_cpu(rsp->DataOffset);
1448}
1449
1450static inline unsigned int
1451read_data_length(char *buf)
1452{
1453 READ_RSP *rsp = (READ_RSP *)buf;
1454 return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
1455 le16_to_cpu(rsp->DataLength);
1456}
1457
1438static int 1458static int
1439cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) 1459cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1440{ 1460{
1441 int length, len; 1461 int length, len;
1442 unsigned int data_offset, remaining, data_len; 1462 unsigned int data_offset, remaining, data_len;
1443 struct cifs_readdata *rdata = mid->callback_data; 1463 struct cifs_readdata *rdata = mid->callback_data;
1444 READ_RSP *rsp = (READ_RSP *)server->smallbuf; 1464 char *buf = server->smallbuf;
1445 unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4; 1465 unsigned int buflen = get_rfc1002_length(buf) + 4;
1446 u64 eof; 1466 u64 eof;
1447 pgoff_t eof_index; 1467 pgoff_t eof_index;
1448 struct page *page, *tpage; 1468 struct page *page, *tpage;
@@ -1455,10 +1475,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1455 * can if there's not enough data. At this point, we've read down to 1475 * can if there's not enough data. At this point, we've read down to
1456 * the Mid. 1476 * the Mid.
1457 */ 1477 */
1458 len = min_t(unsigned int, rfclen, sizeof(*rsp)) - 1478 len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1;
1459 sizeof(struct smb_hdr) + 1;
1460 1479
1461 rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1; 1480 rdata->iov[0].iov_base = buf + header_size() - 1;
1462 rdata->iov[0].iov_len = len; 1481 rdata->iov[0].iov_len = len;
1463 1482
1464 length = cifs_readv_from_socket(server, rdata->iov, 1, len); 1483 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
@@ -1467,7 +1486,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1467 server->total_read += length; 1486 server->total_read += length;
1468 1487
1469 /* Was the SMB read successful? */ 1488 /* Was the SMB read successful? */
1470 rdata->result = map_smb_to_linux_error(&rsp->hdr, false); 1489 rdata->result = map_smb_to_linux_error(buf, false);
1471 if (rdata->result != 0) { 1490 if (rdata->result != 0) {
1472 cFYI(1, "%s: server returned error %d", __func__, 1491 cFYI(1, "%s: server returned error %d", __func__,
1473 rdata->result); 1492 rdata->result);
@@ -1475,14 +1494,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1475 } 1494 }
1476 1495
1477 /* Is there enough to get to the rest of the READ_RSP header? */ 1496 /* Is there enough to get to the rest of the READ_RSP header? */
1478 if (server->total_read < sizeof(READ_RSP)) { 1497 if (server->total_read < read_rsp_size()) {
1479 cFYI(1, "%s: server returned short header. got=%u expected=%zu", 1498 cFYI(1, "%s: server returned short header. got=%u expected=%zu",
1480 __func__, server->total_read, sizeof(READ_RSP)); 1499 __func__, server->total_read, read_rsp_size());
1481 rdata->result = -EIO; 1500 rdata->result = -EIO;
1482 return cifs_readv_discard(server, mid); 1501 return cifs_readv_discard(server, mid);
1483 } 1502 }
1484 1503
1485 data_offset = le16_to_cpu(rsp->DataOffset) + 4; 1504 data_offset = read_data_offset(buf) + 4;
1486 if (data_offset < server->total_read) { 1505 if (data_offset < server->total_read) {
1487 /* 1506 /*
1488 * win2k8 sometimes sends an offset of 0 when the read 1507 * win2k8 sometimes sends an offset of 0 when the read
@@ -1506,7 +1525,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1506 len = data_offset - server->total_read; 1525 len = data_offset - server->total_read;
1507 if (len > 0) { 1526 if (len > 0) {
1508 /* read any junk before data into the rest of smallbuf */ 1527 /* read any junk before data into the rest of smallbuf */
1509 rdata->iov[0].iov_base = server->smallbuf + server->total_read; 1528 rdata->iov[0].iov_base = buf + server->total_read;
1510 rdata->iov[0].iov_len = len; 1529 rdata->iov[0].iov_len = len;
1511 length = cifs_readv_from_socket(server, rdata->iov, 1, len); 1530 length = cifs_readv_from_socket(server, rdata->iov, 1, len);
1512 if (length < 0) 1531 if (length < 0)
@@ -1515,15 +1534,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1515 } 1534 }
1516 1535
1517 /* set up first iov for signature check */ 1536 /* set up first iov for signature check */
1518 rdata->iov[0].iov_base = server->smallbuf; 1537 rdata->iov[0].iov_base = buf;
1519 rdata->iov[0].iov_len = server->total_read; 1538 rdata->iov[0].iov_len = server->total_read;
1520 cFYI(1, "0: iov_base=%p iov_len=%zu", 1539 cFYI(1, "0: iov_base=%p iov_len=%zu",
1521 rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1540 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
1522 1541
1523 /* how much data is in the response? */ 1542 /* how much data is in the response? */
1524 data_len = le16_to_cpu(rsp->DataLengthHigh) << 16; 1543 data_len = read_data_length(buf);
1525 data_len += le16_to_cpu(rsp->DataLength); 1544 if (data_offset + data_len > buflen) {
1526 if (data_offset + data_len > rfclen) {
1527 /* data_len is corrupt -- discard frame */ 1545 /* data_len is corrupt -- discard frame */
1528 rdata->result = -EIO; 1546 rdata->result = -EIO;
1529 return cifs_readv_discard(server, mid); 1547 return cifs_readv_discard(server, mid);
@@ -1602,11 +1620,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
1602 1620
1603 rdata->bytes = length; 1621 rdata->bytes = length;
1604 1622
1605 cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read, 1623 cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
1606 rfclen, remaining); 1624 buflen, remaining);
1607 1625
1608 /* discard anything left over */ 1626 /* discard anything left over */
1609 if (server->total_read < rfclen) 1627 if (server->total_read < buflen)
1610 return cifs_readv_discard(server, mid); 1628 return cifs_readv_discard(server, mid);
1611 1629
1612 dequeue_mid(mid, false); 1630 dequeue_mid(mid, false);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index cb6e757feb52..007d4dfcaf53 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -338,18 +338,6 @@ requeue_echo:
338 queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); 338 queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
339} 339}
340 340
341static inline size_t
342header_size(void)
343{
344 return sizeof(struct smb_hdr);
345}
346
347static inline size_t
348max_header_size(void)
349{
350 return MAX_CIFS_HDR_SIZE;
351}
352
353static bool 341static bool
354allocate_buffers(struct TCP_Server_Info *server) 342allocate_buffers(struct TCP_Server_Info *server)
355{ 343{
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 73e47e84b61a..dd23a321bdda 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -836,8 +836,9 @@ ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
836} 836}
837 837
838int 838int
839map_smb_to_linux_error(struct smb_hdr *smb, bool logErr) 839map_smb_to_linux_error(char *buf, bool logErr)
840{ 840{
841 struct smb_hdr *smb = (struct smb_hdr *)buf;
841 unsigned int i; 842 unsigned int i;
842 int rc = -EIO; /* if transport error smb error may not be set */ 843 int rc = -EIO; /* if transport error smb error may not be set */
843 __u8 smberrclass; 844 __u8 smberrclass;