diff options
Diffstat (limited to 'fs/cifs/cifssmb.c')
| -rw-r--r-- | fs/cifs/cifssmb.c | 377 |
1 files changed, 207 insertions, 170 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df959bae6728..83df937b814e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -339,12 +339,13 @@ static int validate_t2(struct smb_t2_rsp *pSMB) | |||
| 339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) | 339 | get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024) |
| 340 | goto vt2_err; | 340 | goto vt2_err; |
| 341 | 341 | ||
| 342 | /* check that bcc is at least as big as parms + data */ | ||
| 343 | /* check that bcc is less than negotiated smb buffer */ | ||
| 344 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); | 342 | total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount); |
| 345 | if (total_size >= 512) | 343 | if (total_size >= 512) |
| 346 | goto vt2_err; | 344 | goto vt2_err; |
| 347 | 345 | ||
| 346 | /* check that bcc is at least as big as parms + data, and that it is | ||
| 347 | * less than negotiated smb buffer | ||
| 348 | */ | ||
| 348 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); | 349 | total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount); |
| 349 | if (total_size > get_bcc(&pSMB->hdr) || | 350 | if (total_size > get_bcc(&pSMB->hdr) || |
| 350 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) | 351 | total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) |
| @@ -357,6 +358,13 @@ vt2_err: | |||
| 357 | return -EINVAL; | 358 | return -EINVAL; |
| 358 | } | 359 | } |
| 359 | 360 | ||
| 361 | static inline void inc_rfc1001_len(void *pSMB, int count) | ||
| 362 | { | ||
| 363 | struct smb_hdr *hdr = (struct smb_hdr *)pSMB; | ||
| 364 | |||
| 365 | be32_add_cpu(&hdr->smb_buf_length, count); | ||
| 366 | } | ||
| 367 | |||
| 360 | int | 368 | int |
| 361 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | 369 | CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) |
| 362 | { | 370 | { |
| @@ -409,7 +417,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 409 | count += strlen(protocols[i].name) + 1; | 417 | count += strlen(protocols[i].name) + 1; |
| 410 | /* null at end of source and target buffers anyway */ | 418 | /* null at end of source and target buffers anyway */ |
| 411 | } | 419 | } |
| 412 | pSMB->hdr.smb_buf_length += count; | 420 | inc_rfc1001_len(pSMB, count); |
| 413 | pSMB->ByteCount = cpu_to_le16(count); | 421 | pSMB->ByteCount = cpu_to_le16(count); |
| 414 | 422 | ||
| 415 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 423 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
| @@ -541,10 +549,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 541 | server->secType = RawNTLMSSP; | 549 | server->secType = RawNTLMSSP; |
| 542 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 550 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
| 543 | server->secType = LANMAN; | 551 | server->secType = LANMAN; |
| 544 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 545 | else if (secFlags & CIFSSEC_MAY_PLNTXT) | ||
| 546 | server->secType = ?? | ||
| 547 | #endif */ | ||
| 548 | else { | 552 | else { |
| 549 | rc = -EOPNOTSUPP; | 553 | rc = -EOPNOTSUPP; |
| 550 | cERROR(1, "Invalid security type"); | 554 | cERROR(1, "Invalid security type"); |
| @@ -578,7 +582,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 578 | 582 | ||
| 579 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && | 583 | if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && |
| 580 | (server->capabilities & CAP_EXTENDED_SECURITY)) { | 584 | (server->capabilities & CAP_EXTENDED_SECURITY)) { |
| 581 | count = pSMBr->ByteCount; | 585 | count = get_bcc(&pSMBr->hdr); |
| 582 | if (count < 16) { | 586 | if (count < 16) { |
| 583 | rc = -EIO; | 587 | rc = -EIO; |
| 584 | goto neg_err_exit; | 588 | goto neg_err_exit; |
| @@ -732,9 +736,9 @@ CIFSSMBEcho(struct TCP_Server_Info *server) | |||
| 732 | smb->hdr.Tid = 0xffff; | 736 | smb->hdr.Tid = 0xffff; |
| 733 | smb->hdr.WordCount = 1; | 737 | smb->hdr.WordCount = 1; |
| 734 | put_unaligned_le16(1, &smb->EchoCount); | 738 | put_unaligned_le16(1, &smb->EchoCount); |
| 735 | put_bcc_le(1, &smb->hdr); | 739 | put_bcc(1, &smb->hdr); |
| 736 | smb->Data[0] = 'a'; | 740 | smb->Data[0] = 'a'; |
| 737 | smb->hdr.smb_buf_length += 3; | 741 | inc_rfc1001_len(smb, 3); |
| 738 | 742 | ||
| 739 | rc = cifs_call_async(server, (struct smb_hdr *)smb, | 743 | rc = cifs_call_async(server, (struct smb_hdr *)smb, |
| 740 | cifs_echo_callback, server); | 744 | cifs_echo_callback, server); |
| @@ -852,7 +856,7 @@ PsxDelete: | |||
| 852 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 856 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 853 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); | 857 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_UNLINK); |
| 854 | pSMB->Reserved4 = 0; | 858 | pSMB->Reserved4 = 0; |
| 855 | pSMB->hdr.smb_buf_length += byte_count; | 859 | inc_rfc1001_len(pSMB, byte_count); |
| 856 | pSMB->ByteCount = cpu_to_le16(byte_count); | 860 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 857 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 861 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 858 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 862 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -898,7 +902,7 @@ DelFileRetry: | |||
| 898 | pSMB->SearchAttributes = | 902 | pSMB->SearchAttributes = |
| 899 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); | 903 | cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); |
| 900 | pSMB->BufferFormat = 0x04; | 904 | pSMB->BufferFormat = 0x04; |
| 901 | pSMB->hdr.smb_buf_length += name_len + 1; | 905 | inc_rfc1001_len(pSMB, name_len + 1); |
| 902 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 906 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
| 903 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 907 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 904 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 908 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -942,7 +946,7 @@ RmDirRetry: | |||
| 942 | } | 946 | } |
| 943 | 947 | ||
| 944 | pSMB->BufferFormat = 0x04; | 948 | pSMB->BufferFormat = 0x04; |
| 945 | pSMB->hdr.smb_buf_length += name_len + 1; | 949 | inc_rfc1001_len(pSMB, name_len + 1); |
| 946 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 950 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
| 947 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 951 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 948 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 952 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -985,7 +989,7 @@ MkDirRetry: | |||
| 985 | } | 989 | } |
| 986 | 990 | ||
| 987 | pSMB->BufferFormat = 0x04; | 991 | pSMB->BufferFormat = 0x04; |
| 988 | pSMB->hdr.smb_buf_length += name_len + 1; | 992 | inc_rfc1001_len(pSMB, name_len + 1); |
| 989 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 993 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
| 990 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 994 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 991 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 995 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -1063,7 +1067,7 @@ PsxCreat: | |||
| 1063 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 1067 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 1064 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); | 1068 | pSMB->InformationLevel = cpu_to_le16(SMB_POSIX_OPEN); |
| 1065 | pSMB->Reserved4 = 0; | 1069 | pSMB->Reserved4 = 0; |
| 1066 | pSMB->hdr.smb_buf_length += byte_count; | 1070 | inc_rfc1001_len(pSMB, byte_count); |
| 1067 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1071 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 1068 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 1072 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 1069 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 1073 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -1075,7 +1079,7 @@ PsxCreat: | |||
| 1075 | cFYI(1, "copying inode info"); | 1079 | cFYI(1, "copying inode info"); |
| 1076 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1080 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 1077 | 1081 | ||
| 1078 | if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) { | 1082 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP)) { |
| 1079 | rc = -EIO; /* bad smb */ | 1083 | rc = -EIO; /* bad smb */ |
| 1080 | goto psx_create_err; | 1084 | goto psx_create_err; |
| 1081 | } | 1085 | } |
| @@ -1096,7 +1100,7 @@ PsxCreat: | |||
| 1096 | pRetData->Type = cpu_to_le32(-1); /* unknown */ | 1100 | pRetData->Type = cpu_to_le32(-1); /* unknown */ |
| 1097 | cFYI(DBG2, "unknown type"); | 1101 | cFYI(DBG2, "unknown type"); |
| 1098 | } else { | 1102 | } else { |
| 1099 | if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) | 1103 | if (get_bcc(&pSMBr->hdr) < sizeof(OPEN_PSX_RSP) |
| 1100 | + sizeof(FILE_UNIX_BASIC_INFO)) { | 1104 | + sizeof(FILE_UNIX_BASIC_INFO)) { |
| 1101 | cERROR(1, "Open response data too small"); | 1105 | cERROR(1, "Open response data too small"); |
| 1102 | pRetData->Type = cpu_to_le32(-1); | 1106 | pRetData->Type = cpu_to_le32(-1); |
| @@ -1228,7 +1232,7 @@ OldOpenRetry: | |||
| 1228 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); | 1232 | pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); |
| 1229 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); | 1233 | pSMB->OpenFunction = cpu_to_le16(convert_disposition(openDisposition)); |
| 1230 | count += name_len; | 1234 | count += name_len; |
| 1231 | pSMB->hdr.smb_buf_length += count; | 1235 | inc_rfc1001_len(pSMB, count); |
| 1232 | 1236 | ||
| 1233 | pSMB->ByteCount = cpu_to_le16(count); | 1237 | pSMB->ByteCount = cpu_to_le16(count); |
| 1234 | /* long_op set to 1 to allow for oplock break timeouts */ | 1238 | /* long_op set to 1 to allow for oplock break timeouts */ |
| @@ -1341,7 +1345,7 @@ openRetry: | |||
| 1341 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; | 1345 | SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; |
| 1342 | 1346 | ||
| 1343 | count += name_len; | 1347 | count += name_len; |
| 1344 | pSMB->hdr.smb_buf_length += count; | 1348 | inc_rfc1001_len(pSMB, count); |
| 1345 | 1349 | ||
| 1346 | pSMB->ByteCount = cpu_to_le16(count); | 1350 | pSMB->ByteCount = cpu_to_le16(count); |
| 1347 | /* long_op set to 1 to allow for oplock break timeouts */ | 1351 | /* long_op set to 1 to allow for oplock break timeouts */ |
| @@ -1426,7 +1430,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, | |||
| 1426 | } | 1430 | } |
| 1427 | 1431 | ||
| 1428 | iov[0].iov_base = (char *)pSMB; | 1432 | iov[0].iov_base = (char *)pSMB; |
| 1429 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1433 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
| 1430 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1434 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
| 1431 | &resp_buf_type, CIFS_LOG_ERROR); | 1435 | &resp_buf_type, CIFS_LOG_ERROR); |
| 1432 | cifs_stats_inc(&tcon->num_reads); | 1436 | cifs_stats_inc(&tcon->num_reads); |
| @@ -1560,7 +1564,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
| 1560 | 1564 | ||
| 1561 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); | 1565 | pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF); |
| 1562 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); | 1566 | pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16); |
| 1563 | pSMB->hdr.smb_buf_length += byte_count; | 1567 | inc_rfc1001_len(pSMB, byte_count); |
| 1564 | 1568 | ||
| 1565 | if (wct == 14) | 1569 | if (wct == 14) |
| 1566 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1570 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| @@ -1644,11 +1648,12 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
| 1644 | 1648 | ||
| 1645 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); | 1649 | pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF); |
| 1646 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); | 1650 | pSMB->DataLengthHigh = cpu_to_le16(count >> 16); |
| 1647 | smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */ | 1651 | /* header + 1 byte pad */ |
| 1652 | smb_hdr_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 1; | ||
| 1648 | if (wct == 14) | 1653 | if (wct == 14) |
| 1649 | pSMB->hdr.smb_buf_length += count+1; | 1654 | inc_rfc1001_len(pSMB, count + 1); |
| 1650 | else /* wct == 12 */ | 1655 | else /* wct == 12 */ |
| 1651 | pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ | 1656 | inc_rfc1001_len(pSMB, count + 5); /* smb data starts later */ |
| 1652 | if (wct == 14) | 1657 | if (wct == 14) |
| 1653 | pSMB->ByteCount = cpu_to_le16(count + 1); | 1658 | pSMB->ByteCount = cpu_to_le16(count + 1); |
| 1654 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { | 1659 | else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ { |
| @@ -1748,7 +1753,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1748 | /* oplock break */ | 1753 | /* oplock break */ |
| 1749 | count = 0; | 1754 | count = 0; |
| 1750 | } | 1755 | } |
| 1751 | pSMB->hdr.smb_buf_length += count; | 1756 | inc_rfc1001_len(pSMB, count); |
| 1752 | pSMB->ByteCount = cpu_to_le16(count); | 1757 | pSMB->ByteCount = cpu_to_le16(count); |
| 1753 | 1758 | ||
| 1754 | if (waitFlag) { | 1759 | if (waitFlag) { |
| @@ -1839,14 +1844,14 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1839 | pSMB->Fid = smb_file_id; | 1844 | pSMB->Fid = smb_file_id; |
| 1840 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); | 1845 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_LOCK); |
| 1841 | pSMB->Reserved4 = 0; | 1846 | pSMB->Reserved4 = 0; |
| 1842 | pSMB->hdr.smb_buf_length += byte_count; | 1847 | inc_rfc1001_len(pSMB, byte_count); |
| 1843 | pSMB->ByteCount = cpu_to_le16(byte_count); | 1848 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 1844 | if (waitFlag) { | 1849 | if (waitFlag) { |
| 1845 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, | 1850 | rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, |
| 1846 | (struct smb_hdr *) pSMBr, &bytes_returned); | 1851 | (struct smb_hdr *) pSMBr, &bytes_returned); |
| 1847 | } else { | 1852 | } else { |
| 1848 | iov[0].iov_base = (char *)pSMB; | 1853 | iov[0].iov_base = (char *)pSMB; |
| 1849 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 1854 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
| 1850 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, | 1855 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, |
| 1851 | &resp_buf_type, timeout); | 1856 | &resp_buf_type, timeout); |
| 1852 | pSMB = NULL; /* request buf already freed by SendReceive2. Do | 1857 | pSMB = NULL; /* request buf already freed by SendReceive2. Do |
| @@ -1862,7 +1867,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, | |||
| 1862 | __u16 data_count; | 1867 | __u16 data_count; |
| 1863 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 1868 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 1864 | 1869 | ||
| 1865 | if (rc || (pSMBr->ByteCount < sizeof(struct cifs_posix_lock))) { | 1870 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(*parm_data)) { |
| 1866 | rc = -EIO; /* bad smb */ | 1871 | rc = -EIO; /* bad smb */ |
| 1867 | goto plk_err_exit; | 1872 | goto plk_err_exit; |
| 1868 | } | 1873 | } |
| @@ -2012,7 +2017,7 @@ renameRetry: | |||
| 2012 | } | 2017 | } |
| 2013 | 2018 | ||
| 2014 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2019 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
| 2015 | pSMB->hdr.smb_buf_length += count; | 2020 | inc_rfc1001_len(pSMB, count); |
| 2016 | pSMB->ByteCount = cpu_to_le16(count); | 2021 | pSMB->ByteCount = cpu_to_le16(count); |
| 2017 | 2022 | ||
| 2018 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2023 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2092,7 +2097,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, | |||
| 2092 | pSMB->InformationLevel = | 2097 | pSMB->InformationLevel = |
| 2093 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); | 2098 | cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION); |
| 2094 | pSMB->Reserved4 = 0; | 2099 | pSMB->Reserved4 = 0; |
| 2095 | pSMB->hdr.smb_buf_length += byte_count; | 2100 | inc_rfc1001_len(pSMB, byte_count); |
| 2096 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2101 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2097 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, | 2102 | rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB, |
| 2098 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2103 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -2159,7 +2164,7 @@ copyRetry: | |||
| 2159 | } | 2164 | } |
| 2160 | 2165 | ||
| 2161 | count = 1 /* 1st signature byte */ + name_len + name_len2; | 2166 | count = 1 /* 1st signature byte */ + name_len + name_len2; |
| 2162 | pSMB->hdr.smb_buf_length += count; | 2167 | inc_rfc1001_len(pSMB, count); |
| 2163 | pSMB->ByteCount = cpu_to_le16(count); | 2168 | pSMB->ByteCount = cpu_to_le16(count); |
| 2164 | 2169 | ||
| 2165 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2170 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2249,7 +2254,7 @@ createSymLinkRetry: | |||
| 2249 | pSMB->DataOffset = cpu_to_le16(offset); | 2254 | pSMB->DataOffset = cpu_to_le16(offset); |
| 2250 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); | 2255 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK); |
| 2251 | pSMB->Reserved4 = 0; | 2256 | pSMB->Reserved4 = 0; |
| 2252 | pSMB->hdr.smb_buf_length += byte_count; | 2257 | inc_rfc1001_len(pSMB, byte_count); |
| 2253 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2258 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2254 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2259 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 2255 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2260 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -2335,7 +2340,7 @@ createHardLinkRetry: | |||
| 2335 | pSMB->DataOffset = cpu_to_le16(offset); | 2340 | pSMB->DataOffset = cpu_to_le16(offset); |
| 2336 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); | 2341 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK); |
| 2337 | pSMB->Reserved4 = 0; | 2342 | pSMB->Reserved4 = 0; |
| 2338 | pSMB->hdr.smb_buf_length += byte_count; | 2343 | inc_rfc1001_len(pSMB, byte_count); |
| 2339 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2344 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2340 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2345 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 2341 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2346 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -2406,7 +2411,7 @@ winCreateHardLinkRetry: | |||
| 2406 | } | 2411 | } |
| 2407 | 2412 | ||
| 2408 | count = 1 /* string type byte */ + name_len + name_len2; | 2413 | count = 1 /* string type byte */ + name_len + name_len2; |
| 2409 | pSMB->hdr.smb_buf_length += count; | 2414 | inc_rfc1001_len(pSMB, count); |
| 2410 | pSMB->ByteCount = cpu_to_le16(count); | 2415 | pSMB->ByteCount = cpu_to_le16(count); |
| 2411 | 2416 | ||
| 2412 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2417 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2477,7 +2482,7 @@ querySymLinkRetry: | |||
| 2477 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2482 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 2478 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); | 2483 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK); |
| 2479 | pSMB->Reserved4 = 0; | 2484 | pSMB->Reserved4 = 0; |
| 2480 | pSMB->hdr.smb_buf_length += byte_count; | 2485 | inc_rfc1001_len(pSMB, byte_count); |
| 2481 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2486 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2482 | 2487 | ||
| 2483 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2488 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2489,7 +2494,7 @@ querySymLinkRetry: | |||
| 2489 | 2494 | ||
| 2490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2495 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 2491 | /* BB also check enough total bytes returned */ | 2496 | /* BB also check enough total bytes returned */ |
| 2492 | if (rc || (pSMBr->ByteCount < 2)) | 2497 | if (rc || get_bcc(&pSMBr->hdr) < 2) |
| 2493 | rc = -EIO; | 2498 | rc = -EIO; |
| 2494 | else { | 2499 | else { |
| 2495 | bool is_unicode; | 2500 | bool is_unicode; |
| @@ -2516,7 +2521,17 @@ querySymLinkRetry: | |||
| 2516 | return rc; | 2521 | return rc; |
| 2517 | } | 2522 | } |
| 2518 | 2523 | ||
| 2519 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2524 | #ifdef CONFIG_CIFS_SYMLINK_EXPERIMENTAL |
| 2525 | /* | ||
| 2526 | * Recent Windows versions now create symlinks more frequently | ||
| 2527 | * and they use the "reparse point" mechanism below. We can of course | ||
| 2528 | * do symlinks nicely to Samba and other servers which support the | ||
| 2529 | * CIFS Unix Extensions and we can also do SFU symlinks and "client only" | ||
| 2530 | * "MF" symlinks optionally, but for recent Windows we really need to | ||
| 2531 | * reenable the code below and fix the cifs_symlink callers to handle this. | ||
| 2532 | * In the interim this code has been moved to its own config option so | ||
| 2533 | * it is not compiled in by default until callers fixed up and more tested. | ||
| 2534 | */ | ||
| 2520 | int | 2535 | int |
| 2521 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | 2536 | CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, |
| 2522 | const unsigned char *searchName, | 2537 | const unsigned char *searchName, |
| @@ -2561,14 +2576,14 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, | |||
| 2561 | } else { /* decode response */ | 2576 | } else { /* decode response */ |
| 2562 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); | 2577 | __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); |
| 2563 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); | 2578 | __u32 data_count = le32_to_cpu(pSMBr->DataCount); |
| 2564 | if ((pSMBr->ByteCount < 2) || (data_offset > 512)) { | 2579 | if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { |
| 2565 | /* BB also check enough total bytes returned */ | 2580 | /* BB also check enough total bytes returned */ |
| 2566 | rc = -EIO; /* bad smb */ | 2581 | rc = -EIO; /* bad smb */ |
| 2567 | goto qreparse_out; | 2582 | goto qreparse_out; |
| 2568 | } | 2583 | } |
| 2569 | if (data_count && (data_count < 2048)) { | 2584 | if (data_count && (data_count < 2048)) { |
| 2570 | char *end_of_smb = 2 /* sizeof byte count */ + | 2585 | char *end_of_smb = 2 /* sizeof byte count */ + |
| 2571 | pSMBr->ByteCount + (char *)&pSMBr->ByteCount; | 2586 | get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; |
| 2572 | 2587 | ||
| 2573 | struct reparse_data *reparse_buf = | 2588 | struct reparse_data *reparse_buf = |
| 2574 | (struct reparse_data *) | 2589 | (struct reparse_data *) |
| @@ -2618,7 +2633,7 @@ qreparse_out: | |||
| 2618 | 2633 | ||
| 2619 | return rc; | 2634 | return rc; |
| 2620 | } | 2635 | } |
| 2621 | #endif /* CIFS_EXPERIMENTAL */ | 2636 | #endif /* CIFS_SYMLINK_EXPERIMENTAL */ /* BB temporarily unused */ |
| 2622 | 2637 | ||
| 2623 | #ifdef CONFIG_CIFS_POSIX | 2638 | #ifdef CONFIG_CIFS_POSIX |
| 2624 | 2639 | ||
| @@ -2814,7 +2829,7 @@ queryAclRetry: | |||
| 2814 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 2829 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 2815 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); | 2830 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL); |
| 2816 | pSMB->Reserved4 = 0; | 2831 | pSMB->Reserved4 = 0; |
| 2817 | pSMB->hdr.smb_buf_length += byte_count; | 2832 | inc_rfc1001_len(pSMB, byte_count); |
| 2818 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2833 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2819 | 2834 | ||
| 2820 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2835 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2826,8 +2841,8 @@ queryAclRetry: | |||
| 2826 | /* decode response */ | 2841 | /* decode response */ |
| 2827 | 2842 | ||
| 2828 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2843 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 2829 | if (rc || (pSMBr->ByteCount < 2)) | ||
| 2830 | /* BB also check enough total bytes returned */ | 2844 | /* BB also check enough total bytes returned */ |
| 2845 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
| 2831 | rc = -EIO; /* bad smb */ | 2846 | rc = -EIO; /* bad smb */ |
| 2832 | else { | 2847 | else { |
| 2833 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 2848 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -2908,7 +2923,7 @@ setAclRetry: | |||
| 2908 | pSMB->ParameterCount = cpu_to_le16(params); | 2923 | pSMB->ParameterCount = cpu_to_le16(params); |
| 2909 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 2924 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 2910 | pSMB->Reserved4 = 0; | 2925 | pSMB->Reserved4 = 0; |
| 2911 | pSMB->hdr.smb_buf_length += byte_count; | 2926 | inc_rfc1001_len(pSMB, byte_count); |
| 2912 | pSMB->ByteCount = cpu_to_le16(byte_count); | 2927 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 2913 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2928 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 2914 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2929 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -2966,7 +2981,7 @@ GetExtAttrRetry: | |||
| 2966 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); | 2981 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); |
| 2967 | pSMB->Pad = 0; | 2982 | pSMB->Pad = 0; |
| 2968 | pSMB->Fid = netfid; | 2983 | pSMB->Fid = netfid; |
| 2969 | pSMB->hdr.smb_buf_length += byte_count; | 2984 | inc_rfc1001_len(pSMB, byte_count); |
| 2970 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); | 2985 | pSMB->t2.ByteCount = cpu_to_le16(byte_count); |
| 2971 | 2986 | ||
| 2972 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2987 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -2976,8 +2991,8 @@ GetExtAttrRetry: | |||
| 2976 | } else { | 2991 | } else { |
| 2977 | /* decode response */ | 2992 | /* decode response */ |
| 2978 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 2993 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 2979 | if (rc || (pSMBr->ByteCount < 2)) | ||
| 2980 | /* BB also check enough total bytes returned */ | 2994 | /* BB also check enough total bytes returned */ |
| 2995 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
| 2981 | /* If rc should we check for EOPNOSUPP and | 2996 | /* If rc should we check for EOPNOSUPP and |
| 2982 | disable the srvino flag? or in caller? */ | 2997 | disable the srvino flag? or in caller? */ |
| 2983 | rc = -EIO; /* bad smb */ | 2998 | rc = -EIO; /* bad smb */ |
| @@ -3052,6 +3067,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
| 3052 | char *end_of_smb; | 3067 | char *end_of_smb; |
| 3053 | __u32 data_count, data_offset, parm_count, parm_offset; | 3068 | __u32 data_count, data_offset, parm_count, parm_offset; |
| 3054 | struct smb_com_ntransact_rsp *pSMBr; | 3069 | struct smb_com_ntransact_rsp *pSMBr; |
| 3070 | u16 bcc; | ||
| 3055 | 3071 | ||
| 3056 | *pdatalen = 0; | 3072 | *pdatalen = 0; |
| 3057 | *pparmlen = 0; | 3073 | *pparmlen = 0; |
| @@ -3061,8 +3077,8 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
| 3061 | 3077 | ||
| 3062 | pSMBr = (struct smb_com_ntransact_rsp *)buf; | 3078 | pSMBr = (struct smb_com_ntransact_rsp *)buf; |
| 3063 | 3079 | ||
| 3064 | /* ByteCount was converted from little endian in SendReceive */ | 3080 | bcc = get_bcc(&pSMBr->hdr); |
| 3065 | end_of_smb = 2 /* sizeof byte count */ + pSMBr->ByteCount + | 3081 | end_of_smb = 2 /* sizeof byte count */ + bcc + |
| 3066 | (char *)&pSMBr->ByteCount; | 3082 | (char *)&pSMBr->ByteCount; |
| 3067 | 3083 | ||
| 3068 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 3084 | data_offset = le32_to_cpu(pSMBr->DataOffset); |
| @@ -3088,7 +3104,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, | |||
| 3088 | *ppdata, data_count, (data_count + *ppdata), | 3104 | *ppdata, data_count, (data_count + *ppdata), |
| 3089 | end_of_smb, pSMBr); | 3105 | end_of_smb, pSMBr); |
| 3090 | return -EINVAL; | 3106 | return -EINVAL; |
| 3091 | } else if (parm_count + data_count > pSMBr->ByteCount) { | 3107 | } else if (parm_count + data_count > bcc) { |
| 3092 | cFYI(1, "parm count and data count larger than SMB"); | 3108 | cFYI(1, "parm count and data count larger than SMB"); |
| 3093 | return -EINVAL; | 3109 | return -EINVAL; |
| 3094 | } | 3110 | } |
| @@ -3124,9 +3140,9 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, | |||
| 3124 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | | 3140 | pSMB->AclFlags = cpu_to_le32(CIFS_ACL_OWNER | CIFS_ACL_GROUP | |
| 3125 | CIFS_ACL_DACL); | 3141 | CIFS_ACL_DACL); |
| 3126 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ | 3142 | pSMB->ByteCount = cpu_to_le16(11); /* 3 bytes pad + 8 bytes parm */ |
| 3127 | pSMB->hdr.smb_buf_length += 11; | 3143 | inc_rfc1001_len(pSMB, 11); |
| 3128 | iov[0].iov_base = (char *)pSMB; | 3144 | iov[0].iov_base = (char *)pSMB; |
| 3129 | iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; | 3145 | iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4; |
| 3130 | 3146 | ||
| 3131 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, | 3147 | rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, |
| 3132 | 0); | 3148 | 0); |
| @@ -3235,10 +3251,9 @@ setCifsAclRetry: | |||
| 3235 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, | 3251 | memcpy((char *) &pSMBr->hdr.Protocol + data_offset, |
| 3236 | (char *) pntsd, | 3252 | (char *) pntsd, |
| 3237 | acllen); | 3253 | acllen); |
| 3238 | pSMB->hdr.smb_buf_length += (byte_count + data_count); | 3254 | inc_rfc1001_len(pSMB, byte_count + data_count); |
| 3239 | |||
| 3240 | } else | 3255 | } else |
| 3241 | pSMB->hdr.smb_buf_length += byte_count; | 3256 | inc_rfc1001_len(pSMB, byte_count); |
| 3242 | 3257 | ||
| 3243 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3258 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 3244 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3259 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -3289,7 +3304,7 @@ QInfRetry: | |||
| 3289 | } | 3304 | } |
| 3290 | pSMB->BufferFormat = 0x04; | 3305 | pSMB->BufferFormat = 0x04; |
| 3291 | name_len++; /* account for buffer type byte */ | 3306 | name_len++; /* account for buffer type byte */ |
| 3292 | pSMB->hdr.smb_buf_length += (__u16) name_len; | 3307 | inc_rfc1001_len(pSMB, (__u16)name_len); |
| 3293 | pSMB->ByteCount = cpu_to_le16(name_len); | 3308 | pSMB->ByteCount = cpu_to_le16(name_len); |
| 3294 | 3309 | ||
| 3295 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3310 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -3364,7 +3379,7 @@ QFileInfoRetry: | |||
| 3364 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3379 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
| 3365 | pSMB->Pad = 0; | 3380 | pSMB->Pad = 0; |
| 3366 | pSMB->Fid = netfid; | 3381 | pSMB->Fid = netfid; |
| 3367 | pSMB->hdr.smb_buf_length += byte_count; | 3382 | inc_rfc1001_len(pSMB, byte_count); |
| 3368 | 3383 | ||
| 3369 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3384 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 3370 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3385 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -3375,7 +3390,7 @@ QFileInfoRetry: | |||
| 3375 | 3390 | ||
| 3376 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3391 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
| 3377 | rc = -EIO; | 3392 | rc = -EIO; |
| 3378 | else if (pSMBr->ByteCount < 40) | 3393 | else if (get_bcc(&pSMBr->hdr) < 40) |
| 3379 | rc = -EIO; /* bad smb */ | 3394 | rc = -EIO; /* bad smb */ |
| 3380 | else if (pFindData) { | 3395 | else if (pFindData) { |
| 3381 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 3396 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -3451,7 +3466,7 @@ QPathInfoRetry: | |||
| 3451 | else | 3466 | else |
| 3452 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); | 3467 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO); |
| 3453 | pSMB->Reserved4 = 0; | 3468 | pSMB->Reserved4 = 0; |
| 3454 | pSMB->hdr.smb_buf_length += byte_count; | 3469 | inc_rfc1001_len(pSMB, byte_count); |
| 3455 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3470 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 3456 | 3471 | ||
| 3457 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3472 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -3463,9 +3478,9 @@ QPathInfoRetry: | |||
| 3463 | 3478 | ||
| 3464 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ | 3479 | if (rc) /* BB add auto retry on EOPNOTSUPP? */ |
| 3465 | rc = -EIO; | 3480 | rc = -EIO; |
| 3466 | else if (!legacy && (pSMBr->ByteCount < 40)) | 3481 | else if (!legacy && get_bcc(&pSMBr->hdr) < 40) |
| 3467 | rc = -EIO; /* bad smb */ | 3482 | rc = -EIO; /* bad smb */ |
| 3468 | else if (legacy && (pSMBr->ByteCount < 24)) | 3483 | else if (legacy && get_bcc(&pSMBr->hdr) < 24) |
| 3469 | rc = -EIO; /* 24 or 26 expected but we do not read | 3484 | rc = -EIO; /* 24 or 26 expected but we do not read |
| 3470 | last field */ | 3485 | last field */ |
| 3471 | else if (pFindData) { | 3486 | else if (pFindData) { |
| @@ -3532,7 +3547,7 @@ UnixQFileInfoRetry: | |||
| 3532 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3547 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
| 3533 | pSMB->Pad = 0; | 3548 | pSMB->Pad = 0; |
| 3534 | pSMB->Fid = netfid; | 3549 | pSMB->Fid = netfid; |
| 3535 | pSMB->hdr.smb_buf_length += byte_count; | 3550 | inc_rfc1001_len(pSMB, byte_count); |
| 3536 | 3551 | ||
| 3537 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3552 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 3538 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 3553 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -3541,7 +3556,7 @@ UnixQFileInfoRetry: | |||
| 3541 | } else { /* decode response */ | 3556 | } else { /* decode response */ |
| 3542 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3557 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 3543 | 3558 | ||
| 3544 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3559 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
| 3545 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3560 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
| 3546 | "Unix Extensions can be disabled on mount " | 3561 | "Unix Extensions can be disabled on mount " |
| 3547 | "by specifying the nosfu mount option."); | 3562 | "by specifying the nosfu mount option."); |
| @@ -3617,7 +3632,7 @@ UnixQPathInfoRetry: | |||
| 3617 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3632 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 3618 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); | 3633 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC); |
| 3619 | pSMB->Reserved4 = 0; | 3634 | pSMB->Reserved4 = 0; |
| 3620 | pSMB->hdr.smb_buf_length += byte_count; | 3635 | inc_rfc1001_len(pSMB, byte_count); |
| 3621 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3636 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 3622 | 3637 | ||
| 3623 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3638 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -3627,7 +3642,7 @@ UnixQPathInfoRetry: | |||
| 3627 | } else { /* decode response */ | 3642 | } else { /* decode response */ |
| 3628 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 3643 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 3629 | 3644 | ||
| 3630 | if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { | 3645 | if (rc || get_bcc(&pSMBr->hdr) < sizeof(FILE_UNIX_BASIC_INFO)) { |
| 3631 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" | 3646 | cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" |
| 3632 | "Unix Extensions can be disabled on mount " | 3647 | "Unix Extensions can be disabled on mount " |
| 3633 | "by specifying the nosfu mount option."); | 3648 | "by specifying the nosfu mount option."); |
| @@ -3731,7 +3746,7 @@ findFirstRetry: | |||
| 3731 | 3746 | ||
| 3732 | /* BB what should we set StorageType to? Does it matter? BB */ | 3747 | /* BB what should we set StorageType to? Does it matter? BB */ |
| 3733 | pSMB->SearchStorageType = 0; | 3748 | pSMB->SearchStorageType = 0; |
| 3734 | pSMB->hdr.smb_buf_length += byte_count; | 3749 | inc_rfc1001_len(pSMB, byte_count); |
| 3735 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3750 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 3736 | 3751 | ||
| 3737 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3752 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -3860,7 +3875,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, | |||
| 3860 | byte_count = params + 1 /* pad */ ; | 3875 | byte_count = params + 1 /* pad */ ; |
| 3861 | pSMB->TotalParameterCount = cpu_to_le16(params); | 3876 | pSMB->TotalParameterCount = cpu_to_le16(params); |
| 3862 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 3877 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 3863 | pSMB->hdr.smb_buf_length += byte_count; | 3878 | inc_rfc1001_len(pSMB, byte_count); |
| 3864 | pSMB->ByteCount = cpu_to_le16(byte_count); | 3879 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 3865 | 3880 | ||
| 3866 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 3881 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4022,7 +4037,7 @@ GetInodeNumberRetry: | |||
| 4022 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 4037 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 4023 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); | 4038 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO); |
| 4024 | pSMB->Reserved4 = 0; | 4039 | pSMB->Reserved4 = 0; |
| 4025 | pSMB->hdr.smb_buf_length += byte_count; | 4040 | inc_rfc1001_len(pSMB, byte_count); |
| 4026 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4041 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4027 | 4042 | ||
| 4028 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4043 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4032,8 +4047,8 @@ GetInodeNumberRetry: | |||
| 4032 | } else { | 4047 | } else { |
| 4033 | /* decode response */ | 4048 | /* decode response */ |
| 4034 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4049 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4035 | if (rc || (pSMBr->ByteCount < 2)) | ||
| 4036 | /* BB also check enough total bytes returned */ | 4050 | /* BB also check enough total bytes returned */ |
| 4051 | if (rc || get_bcc(&pSMBr->hdr) < 2) | ||
| 4037 | /* If rc should we check for EOPNOSUPP and | 4052 | /* If rc should we check for EOPNOSUPP and |
| 4038 | disable the srvino flag? or in caller? */ | 4053 | disable the srvino flag? or in caller? */ |
| 4039 | rc = -EIO; /* bad smb */ | 4054 | rc = -EIO; /* bad smb */ |
| @@ -4246,7 +4261,7 @@ getDFSRetry: | |||
| 4246 | pSMB->ParameterCount = cpu_to_le16(params); | 4261 | pSMB->ParameterCount = cpu_to_le16(params); |
| 4247 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4262 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 4248 | pSMB->MaxReferralLevel = cpu_to_le16(3); | 4263 | pSMB->MaxReferralLevel = cpu_to_le16(3); |
| 4249 | pSMB->hdr.smb_buf_length += byte_count; | 4264 | inc_rfc1001_len(pSMB, byte_count); |
| 4250 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4265 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4251 | 4266 | ||
| 4252 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, | 4267 | rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, |
| @@ -4258,13 +4273,13 @@ getDFSRetry: | |||
| 4258 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4273 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4259 | 4274 | ||
| 4260 | /* BB Also check if enough total bytes returned? */ | 4275 | /* BB Also check if enough total bytes returned? */ |
| 4261 | if (rc || (pSMBr->ByteCount < 17)) { | 4276 | if (rc || get_bcc(&pSMBr->hdr) < 17) { |
| 4262 | rc = -EIO; /* bad smb */ | 4277 | rc = -EIO; /* bad smb */ |
| 4263 | goto GetDFSRefExit; | 4278 | goto GetDFSRefExit; |
| 4264 | } | 4279 | } |
| 4265 | 4280 | ||
| 4266 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", | 4281 | cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", |
| 4267 | pSMBr->ByteCount, | 4282 | get_bcc(&pSMBr->hdr), |
| 4268 | le16_to_cpu(pSMBr->t2.DataOffset)); | 4283 | le16_to_cpu(pSMBr->t2.DataOffset)); |
| 4269 | 4284 | ||
| 4270 | /* parse returned result into more usable form */ | 4285 | /* parse returned result into more usable form */ |
| @@ -4320,7 +4335,7 @@ oldQFSInfoRetry: | |||
| 4320 | pSMB->Reserved3 = 0; | 4335 | pSMB->Reserved3 = 0; |
| 4321 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4336 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4322 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); | 4337 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION); |
| 4323 | pSMB->hdr.smb_buf_length += byte_count; | 4338 | inc_rfc1001_len(pSMB, byte_count); |
| 4324 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4339 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4325 | 4340 | ||
| 4326 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4341 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4330,12 +4345,12 @@ oldQFSInfoRetry: | |||
| 4330 | } else { /* decode response */ | 4345 | } else { /* decode response */ |
| 4331 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4346 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4332 | 4347 | ||
| 4333 | if (rc || (pSMBr->ByteCount < 18)) | 4348 | if (rc || get_bcc(&pSMBr->hdr) < 18) |
| 4334 | rc = -EIO; /* bad smb */ | 4349 | rc = -EIO; /* bad smb */ |
| 4335 | else { | 4350 | else { |
| 4336 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4351 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| 4337 | cFYI(1, "qfsinf resp BCC: %d Offset %d", | 4352 | cFYI(1, "qfsinf resp BCC: %d Offset %d", |
| 4338 | pSMBr->ByteCount, data_offset); | 4353 | get_bcc(&pSMBr->hdr), data_offset); |
| 4339 | 4354 | ||
| 4340 | response_data = (FILE_SYSTEM_ALLOC_INFO *) | 4355 | response_data = (FILE_SYSTEM_ALLOC_INFO *) |
| 4341 | (((char *) &pSMBr->hdr.Protocol) + data_offset); | 4356 | (((char *) &pSMBr->hdr.Protocol) + data_offset); |
| @@ -4399,7 +4414,7 @@ QFSInfoRetry: | |||
| 4399 | pSMB->Reserved3 = 0; | 4414 | pSMB->Reserved3 = 0; |
| 4400 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4415 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4401 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); | 4416 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO); |
| 4402 | pSMB->hdr.smb_buf_length += byte_count; | 4417 | inc_rfc1001_len(pSMB, byte_count); |
| 4403 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4418 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4404 | 4419 | ||
| 4405 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4420 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4409,7 +4424,7 @@ QFSInfoRetry: | |||
| 4409 | } else { /* decode response */ | 4424 | } else { /* decode response */ |
| 4410 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4425 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4411 | 4426 | ||
| 4412 | if (rc || (pSMBr->ByteCount < 24)) | 4427 | if (rc || get_bcc(&pSMBr->hdr) < 24) |
| 4413 | rc = -EIO; /* bad smb */ | 4428 | rc = -EIO; /* bad smb */ |
| 4414 | else { | 4429 | else { |
| 4415 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4430 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -4479,7 +4494,7 @@ QFSAttributeRetry: | |||
| 4479 | pSMB->Reserved3 = 0; | 4494 | pSMB->Reserved3 = 0; |
| 4480 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4495 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4481 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); | 4496 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO); |
| 4482 | pSMB->hdr.smb_buf_length += byte_count; | 4497 | inc_rfc1001_len(pSMB, byte_count); |
| 4483 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4498 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4484 | 4499 | ||
| 4485 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4500 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4489,7 +4504,7 @@ QFSAttributeRetry: | |||
| 4489 | } else { /* decode response */ | 4504 | } else { /* decode response */ |
| 4490 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4505 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4491 | 4506 | ||
| 4492 | if (rc || (pSMBr->ByteCount < 13)) { | 4507 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
| 4493 | /* BB also check if enough bytes returned */ | 4508 | /* BB also check if enough bytes returned */ |
| 4494 | rc = -EIO; /* bad smb */ | 4509 | rc = -EIO; /* bad smb */ |
| 4495 | } else { | 4510 | } else { |
| @@ -4550,7 +4565,7 @@ QFSDeviceRetry: | |||
| 4550 | pSMB->Reserved3 = 0; | 4565 | pSMB->Reserved3 = 0; |
| 4551 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4566 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4552 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); | 4567 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO); |
| 4553 | pSMB->hdr.smb_buf_length += byte_count; | 4568 | inc_rfc1001_len(pSMB, byte_count); |
| 4554 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4569 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4555 | 4570 | ||
| 4556 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4571 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4560,7 +4575,8 @@ QFSDeviceRetry: | |||
| 4560 | } else { /* decode response */ | 4575 | } else { /* decode response */ |
| 4561 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4576 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4562 | 4577 | ||
| 4563 | if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO))) | 4578 | if (rc || get_bcc(&pSMBr->hdr) < |
| 4579 | sizeof(FILE_SYSTEM_DEVICE_INFO)) | ||
| 4564 | rc = -EIO; /* bad smb */ | 4580 | rc = -EIO; /* bad smb */ |
| 4565 | else { | 4581 | else { |
| 4566 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4582 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -4619,7 +4635,7 @@ QFSUnixRetry: | |||
| 4619 | pSMB->Reserved3 = 0; | 4635 | pSMB->Reserved3 = 0; |
| 4620 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4636 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4621 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); | 4637 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO); |
| 4622 | pSMB->hdr.smb_buf_length += byte_count; | 4638 | inc_rfc1001_len(pSMB, byte_count); |
| 4623 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4639 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4624 | 4640 | ||
| 4625 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4641 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4629,7 +4645,7 @@ QFSUnixRetry: | |||
| 4629 | } else { /* decode response */ | 4645 | } else { /* decode response */ |
| 4630 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4646 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4631 | 4647 | ||
| 4632 | if (rc || (pSMBr->ByteCount < 13)) { | 4648 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
| 4633 | rc = -EIO; /* bad smb */ | 4649 | rc = -EIO; /* bad smb */ |
| 4634 | } else { | 4650 | } else { |
| 4635 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4651 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -4702,7 +4718,7 @@ SETFSUnixRetry: | |||
| 4702 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); | 4718 | pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION); |
| 4703 | pSMB->ClientUnixCap = cpu_to_le64(cap); | 4719 | pSMB->ClientUnixCap = cpu_to_le64(cap); |
| 4704 | 4720 | ||
| 4705 | pSMB->hdr.smb_buf_length += byte_count; | 4721 | inc_rfc1001_len(pSMB, byte_count); |
| 4706 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4722 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4707 | 4723 | ||
| 4708 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4724 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4764,7 +4780,7 @@ QFSPosixRetry: | |||
| 4764 | pSMB->Reserved3 = 0; | 4780 | pSMB->Reserved3 = 0; |
| 4765 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); | 4781 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION); |
| 4766 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); | 4782 | pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO); |
| 4767 | pSMB->hdr.smb_buf_length += byte_count; | 4783 | inc_rfc1001_len(pSMB, byte_count); |
| 4768 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4784 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4769 | 4785 | ||
| 4770 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4786 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4774,7 +4790,7 @@ QFSPosixRetry: | |||
| 4774 | } else { /* decode response */ | 4790 | } else { /* decode response */ |
| 4775 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 4791 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 4776 | 4792 | ||
| 4777 | if (rc || (pSMBr->ByteCount < 13)) { | 4793 | if (rc || get_bcc(&pSMBr->hdr) < 13) { |
| 4778 | rc = -EIO; /* bad smb */ | 4794 | rc = -EIO; /* bad smb */ |
| 4779 | } else { | 4795 | } else { |
| 4780 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | 4796 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
| @@ -4890,7 +4906,7 @@ SetEOFRetry: | |||
| 4890 | pSMB->ParameterCount = cpu_to_le16(params); | 4906 | pSMB->ParameterCount = cpu_to_le16(params); |
| 4891 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 4907 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 4892 | pSMB->Reserved4 = 0; | 4908 | pSMB->Reserved4 = 0; |
| 4893 | pSMB->hdr.smb_buf_length += byte_count; | 4909 | inc_rfc1001_len(pSMB, byte_count); |
| 4894 | parm_data->FileSize = cpu_to_le64(size); | 4910 | parm_data->FileSize = cpu_to_le64(size); |
| 4895 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4911 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4896 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 4912 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -4969,7 +4985,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, | |||
| 4969 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); | 4985 | cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO); |
| 4970 | } | 4986 | } |
| 4971 | pSMB->Reserved4 = 0; | 4987 | pSMB->Reserved4 = 0; |
| 4972 | pSMB->hdr.smb_buf_length += byte_count; | 4988 | inc_rfc1001_len(pSMB, byte_count); |
| 4973 | pSMB->ByteCount = cpu_to_le16(byte_count); | 4989 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 4974 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 4990 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
| 4975 | if (rc) { | 4991 | if (rc) { |
| @@ -5037,7 +5053,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
| 5037 | else | 5053 | else |
| 5038 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5054 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
| 5039 | pSMB->Reserved4 = 0; | 5055 | pSMB->Reserved4 = 0; |
| 5040 | pSMB->hdr.smb_buf_length += byte_count; | 5056 | inc_rfc1001_len(pSMB, byte_count); |
| 5041 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5057 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5042 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5058 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
| 5043 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5059 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
| @@ -5096,7 +5112,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, | |||
| 5096 | pSMB->Fid = fid; | 5112 | pSMB->Fid = fid; |
| 5097 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); | 5113 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_DISPOSITION_INFO); |
| 5098 | pSMB->Reserved4 = 0; | 5114 | pSMB->Reserved4 = 0; |
| 5099 | pSMB->hdr.smb_buf_length += byte_count; | 5115 | inc_rfc1001_len(pSMB, byte_count); |
| 5100 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5116 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5101 | *data_offset = delete_file ? 1 : 0; | 5117 | *data_offset = delete_file ? 1 : 0; |
| 5102 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5118 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); |
| @@ -5169,7 +5185,7 @@ SetTimesRetry: | |||
| 5169 | else | 5185 | else |
| 5170 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); | 5186 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO); |
| 5171 | pSMB->Reserved4 = 0; | 5187 | pSMB->Reserved4 = 0; |
| 5172 | pSMB->hdr.smb_buf_length += byte_count; | 5188 | inc_rfc1001_len(pSMB, byte_count); |
| 5173 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5189 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
| 5174 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5190 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5175 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5191 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -5221,7 +5237,7 @@ SetAttrLgcyRetry: | |||
| 5221 | } | 5237 | } |
| 5222 | pSMB->attr = cpu_to_le16(dos_attrs); | 5238 | pSMB->attr = cpu_to_le16(dos_attrs); |
| 5223 | pSMB->BufferFormat = 0x04; | 5239 | pSMB->BufferFormat = 0x04; |
| 5224 | pSMB->hdr.smb_buf_length += name_len + 1; | 5240 | inc_rfc1001_len(pSMB, name_len + 1); |
| 5225 | pSMB->ByteCount = cpu_to_le16(name_len + 1); | 5241 | pSMB->ByteCount = cpu_to_le16(name_len + 1); |
| 5226 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5242 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 5227 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5243 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -5326,7 +5342,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | |||
| 5326 | pSMB->Fid = fid; | 5342 | pSMB->Fid = fid; |
| 5327 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5343 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
| 5328 | pSMB->Reserved4 = 0; | 5344 | pSMB->Reserved4 = 0; |
| 5329 | pSMB->hdr.smb_buf_length += byte_count; | 5345 | inc_rfc1001_len(pSMB, byte_count); |
| 5330 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5346 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5331 | 5347 | ||
| 5332 | cifs_fill_unix_set_info(data_offset, args); | 5348 | cifs_fill_unix_set_info(data_offset, args); |
| @@ -5402,7 +5418,7 @@ setPermsRetry: | |||
| 5402 | pSMB->TotalDataCount = pSMB->DataCount; | 5418 | pSMB->TotalDataCount = pSMB->DataCount; |
| 5403 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | 5419 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); |
| 5404 | pSMB->Reserved4 = 0; | 5420 | pSMB->Reserved4 = 0; |
| 5405 | pSMB->hdr.smb_buf_length += byte_count; | 5421 | inc_rfc1001_len(pSMB, byte_count); |
| 5406 | 5422 | ||
| 5407 | cifs_fill_unix_set_info(data_offset, args); | 5423 | cifs_fill_unix_set_info(data_offset, args); |
| 5408 | 5424 | ||
| @@ -5418,79 +5434,6 @@ setPermsRetry: | |||
| 5418 | return rc; | 5434 | return rc; |
| 5419 | } | 5435 | } |
| 5420 | 5436 | ||
| 5421 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
| 5422 | const int notify_subdirs, const __u16 netfid, | ||
| 5423 | __u32 filter, struct file *pfile, int multishot, | ||
| 5424 | const struct nls_table *nls_codepage) | ||
| 5425 | { | ||
| 5426 | int rc = 0; | ||
| 5427 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
| 5428 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
| 5429 | struct dir_notify_req *dnotify_req; | ||
| 5430 | int bytes_returned; | ||
| 5431 | |||
| 5432 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
| 5433 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
| 5434 | (void **) &pSMBr); | ||
| 5435 | if (rc) | ||
| 5436 | return rc; | ||
| 5437 | |||
| 5438 | pSMB->TotalParameterCount = 0 ; | ||
| 5439 | pSMB->TotalDataCount = 0; | ||
| 5440 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
| 5441 | /* BB find exact data count max from sess structure BB */ | ||
| 5442 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
| 5443 | /* BB VERIFY verify which is correct for above BB */ | ||
| 5444 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
| 5445 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
| 5446 | |||
| 5447 | pSMB->MaxSetupCount = 4; | ||
| 5448 | pSMB->Reserved = 0; | ||
| 5449 | pSMB->ParameterOffset = 0; | ||
| 5450 | pSMB->DataCount = 0; | ||
| 5451 | pSMB->DataOffset = 0; | ||
| 5452 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
| 5453 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
| 5454 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
| 5455 | if (notify_subdirs) | ||
| 5456 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
| 5457 | pSMB->Reserved2 = 0; | ||
| 5458 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
| 5459 | pSMB->Fid = netfid; /* file handle always le */ | ||
| 5460 | pSMB->ByteCount = 0; | ||
| 5461 | |||
| 5462 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
| 5463 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
| 5464 | CIFS_ASYNC_OP); | ||
| 5465 | if (rc) { | ||
| 5466 | cFYI(1, "Error in Notify = %d", rc); | ||
| 5467 | } else { | ||
| 5468 | /* Add file to outstanding requests */ | ||
| 5469 | /* BB change to kmem cache alloc */ | ||
| 5470 | dnotify_req = kmalloc( | ||
| 5471 | sizeof(struct dir_notify_req), | ||
| 5472 | GFP_KERNEL); | ||
| 5473 | if (dnotify_req) { | ||
| 5474 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
| 5475 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
| 5476 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
| 5477 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
| 5478 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
| 5479 | dnotify_req->netfid = netfid; | ||
| 5480 | dnotify_req->pfile = pfile; | ||
| 5481 | dnotify_req->filter = filter; | ||
| 5482 | dnotify_req->multishot = multishot; | ||
| 5483 | spin_lock(&GlobalMid_Lock); | ||
| 5484 | list_add_tail(&dnotify_req->lhead, | ||
| 5485 | &GlobalDnotifyReqList); | ||
| 5486 | spin_unlock(&GlobalMid_Lock); | ||
| 5487 | } else | ||
| 5488 | rc = -ENOMEM; | ||
| 5489 | } | ||
| 5490 | cifs_buf_release(pSMB); | ||
| 5491 | return rc; | ||
| 5492 | } | ||
| 5493 | |||
| 5494 | #ifdef CONFIG_CIFS_XATTR | 5437 | #ifdef CONFIG_CIFS_XATTR |
| 5495 | /* | 5438 | /* |
| 5496 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common | 5439 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common |
| @@ -5560,7 +5503,7 @@ QAllEAsRetry: | |||
| 5560 | pSMB->ParameterCount = pSMB->TotalParameterCount; | 5503 | pSMB->ParameterCount = pSMB->TotalParameterCount; |
| 5561 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); | 5504 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); |
| 5562 | pSMB->Reserved4 = 0; | 5505 | pSMB->Reserved4 = 0; |
| 5563 | pSMB->hdr.smb_buf_length += byte_count; | 5506 | inc_rfc1001_len(pSMB, byte_count); |
| 5564 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5507 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5565 | 5508 | ||
| 5566 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5509 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| @@ -5576,7 +5519,7 @@ QAllEAsRetry: | |||
| 5576 | of these trans2 responses */ | 5519 | of these trans2 responses */ |
| 5577 | 5520 | ||
| 5578 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5521 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
| 5579 | if (rc || (pSMBr->ByteCount < 4)) { | 5522 | if (rc || get_bcc(&pSMBr->hdr) < 4) { |
| 5580 | rc = -EIO; /* bad smb */ | 5523 | rc = -EIO; /* bad smb */ |
| 5581 | goto QAllEAsOut; | 5524 | goto QAllEAsOut; |
| 5582 | } | 5525 | } |
| @@ -5773,7 +5716,7 @@ SetEARetry: | |||
| 5773 | pSMB->ParameterCount = cpu_to_le16(params); | 5716 | pSMB->ParameterCount = cpu_to_le16(params); |
| 5774 | pSMB->TotalParameterCount = pSMB->ParameterCount; | 5717 | pSMB->TotalParameterCount = pSMB->ParameterCount; |
| 5775 | pSMB->Reserved4 = 0; | 5718 | pSMB->Reserved4 = 0; |
| 5776 | pSMB->hdr.smb_buf_length += byte_count; | 5719 | inc_rfc1001_len(pSMB, byte_count); |
| 5777 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5720 | pSMB->ByteCount = cpu_to_le16(byte_count); |
| 5778 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5721 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, |
| 5779 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5722 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
| @@ -5787,5 +5730,99 @@ SetEARetry: | |||
| 5787 | 5730 | ||
| 5788 | return rc; | 5731 | return rc; |
| 5789 | } | 5732 | } |
| 5790 | |||
| 5791 | #endif | 5733 | #endif |
| 5734 | |||
| 5735 | #ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* BB unused temporarily */ | ||
| 5736 | /* | ||
| 5737 | * Years ago the kernel added a "dnotify" function for Samba server, | ||
| 5738 | * to allow network clients (such as Windows) to display updated | ||
| 5739 | * lists of files in directory listings automatically when | ||
| 5740 | * files are added by one user when another user has the | ||
| 5741 | * same directory open on their desktop. The Linux cifs kernel | ||
| 5742 | * client hooked into the kernel side of this interface for | ||
| 5743 | * the same reason, but ironically when the VFS moved from | ||
| 5744 | * "dnotify" to "inotify" it became harder to plug in Linux | ||
| 5745 | * network file system clients (the most obvious use case | ||
| 5746 | * for notify interfaces is when multiple users can update | ||
| 5747 | * the contents of the same directory - exactly what network | ||
| 5748 | * file systems can do) although the server (Samba) could | ||
| 5749 | * still use it. For the short term we leave the worker | ||
| 5750 | * function ifdeffed out (below) until inotify is fixed | ||
| 5751 | * in the VFS to make it easier to plug in network file | ||
| 5752 | * system clients. If inotify turns out to be permanently | ||
| 5753 | * incompatible for network fs clients, we could instead simply | ||
| 5754 | * expose this config flag by adding a future cifs (and smb2) notify ioctl. | ||
| 5755 | */ | ||
| 5756 | int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | ||
| 5757 | const int notify_subdirs, const __u16 netfid, | ||
| 5758 | __u32 filter, struct file *pfile, int multishot, | ||
| 5759 | const struct nls_table *nls_codepage) | ||
| 5760 | { | ||
| 5761 | int rc = 0; | ||
| 5762 | struct smb_com_transaction_change_notify_req *pSMB = NULL; | ||
| 5763 | struct smb_com_ntransaction_change_notify_rsp *pSMBr = NULL; | ||
| 5764 | struct dir_notify_req *dnotify_req; | ||
| 5765 | int bytes_returned; | ||
| 5766 | |||
| 5767 | cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); | ||
| 5768 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | ||
| 5769 | (void **) &pSMBr); | ||
| 5770 | if (rc) | ||
| 5771 | return rc; | ||
| 5772 | |||
| 5773 | pSMB->TotalParameterCount = 0 ; | ||
| 5774 | pSMB->TotalDataCount = 0; | ||
| 5775 | pSMB->MaxParameterCount = cpu_to_le32(2); | ||
| 5776 | /* BB find exact data count max from sess structure BB */ | ||
| 5777 | pSMB->MaxDataCount = 0; /* same in little endian or be */ | ||
| 5778 | /* BB VERIFY verify which is correct for above BB */ | ||
| 5779 | pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - | ||
| 5780 | MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); | ||
| 5781 | |||
| 5782 | pSMB->MaxSetupCount = 4; | ||
| 5783 | pSMB->Reserved = 0; | ||
| 5784 | pSMB->ParameterOffset = 0; | ||
| 5785 | pSMB->DataCount = 0; | ||
| 5786 | pSMB->DataOffset = 0; | ||
| 5787 | pSMB->SetupCount = 4; /* single byte does not need le conversion */ | ||
| 5788 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE); | ||
| 5789 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
| 5790 | if (notify_subdirs) | ||
| 5791 | pSMB->WatchTree = 1; /* one byte - no le conversion needed */ | ||
| 5792 | pSMB->Reserved2 = 0; | ||
| 5793 | pSMB->CompletionFilter = cpu_to_le32(filter); | ||
| 5794 | pSMB->Fid = netfid; /* file handle always le */ | ||
| 5795 | pSMB->ByteCount = 0; | ||
| 5796 | |||
| 5797 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | ||
| 5798 | (struct smb_hdr *)pSMBr, &bytes_returned, | ||
| 5799 | CIFS_ASYNC_OP); | ||
| 5800 | if (rc) { | ||
| 5801 | cFYI(1, "Error in Notify = %d", rc); | ||
| 5802 | } else { | ||
| 5803 | /* Add file to outstanding requests */ | ||
| 5804 | /* BB change to kmem cache alloc */ | ||
| 5805 | dnotify_req = kmalloc( | ||
| 5806 | sizeof(struct dir_notify_req), | ||
| 5807 | GFP_KERNEL); | ||
| 5808 | if (dnotify_req) { | ||
| 5809 | dnotify_req->Pid = pSMB->hdr.Pid; | ||
| 5810 | dnotify_req->PidHigh = pSMB->hdr.PidHigh; | ||
| 5811 | dnotify_req->Mid = pSMB->hdr.Mid; | ||
| 5812 | dnotify_req->Tid = pSMB->hdr.Tid; | ||
| 5813 | dnotify_req->Uid = pSMB->hdr.Uid; | ||
| 5814 | dnotify_req->netfid = netfid; | ||
| 5815 | dnotify_req->pfile = pfile; | ||
| 5816 | dnotify_req->filter = filter; | ||
| 5817 | dnotify_req->multishot = multishot; | ||
| 5818 | spin_lock(&GlobalMid_Lock); | ||
| 5819 | list_add_tail(&dnotify_req->lhead, | ||
| 5820 | &GlobalDnotifyReqList); | ||
| 5821 | spin_unlock(&GlobalMid_Lock); | ||
| 5822 | } else | ||
| 5823 | rc = -ENOMEM; | ||
| 5824 | } | ||
| 5825 | cifs_buf_release(pSMB); | ||
| 5826 | return rc; | ||
| 5827 | } | ||
| 5828 | #endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ | ||
