diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 12 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 58 | ||||
-rw-r--r-- | fs/cifs/connect.c | 12 | ||||
-rw-r--r-- | fs/cifs/netmisc.c | 3 |
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 | ||
344 | static inline size_t | ||
345 | header_size(void) | ||
346 | { | ||
347 | return sizeof(struct smb_hdr); | ||
348 | } | ||
349 | |||
350 | static inline size_t | ||
351 | max_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); | |||
106 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); | 106 | extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); |
107 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | 107 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, |
108 | const unsigned short int port); | 108 | const unsigned short int port); |
109 | extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr); | 109 | extern int map_smb_to_linux_error(char *buf, bool logErr); |
110 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 110 | extern 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) | |||
1414 | static int | 1414 | static int |
1415 | cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) | 1415 | cifs_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 | ||
1437 | static inline size_t | ||
1438 | read_rsp_size(void) | ||
1439 | { | ||
1440 | return sizeof(READ_RSP); | ||
1441 | } | ||
1442 | |||
1443 | static inline unsigned int | ||
1444 | read_data_offset(char *buf) | ||
1445 | { | ||
1446 | READ_RSP *rsp = (READ_RSP *)buf; | ||
1447 | return le16_to_cpu(rsp->DataOffset); | ||
1448 | } | ||
1449 | |||
1450 | static inline unsigned int | ||
1451 | read_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 | |||
1438 | static int | 1458 | static int |
1439 | cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) | 1459 | cifs_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 | ||
341 | static inline size_t | ||
342 | header_size(void) | ||
343 | { | ||
344 | return sizeof(struct smb_hdr); | ||
345 | } | ||
346 | |||
347 | static inline size_t | ||
348 | max_header_size(void) | ||
349 | { | ||
350 | return MAX_CIFS_HDR_SIZE; | ||
351 | } | ||
352 | |||
353 | static bool | 341 | static bool |
354 | allocate_buffers(struct TCP_Server_Info *server) | 342 | allocate_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 | ||
838 | int | 838 | int |
839 | map_smb_to_linux_error(struct smb_hdr *smb, bool logErr) | 839 | map_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; |