aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/cifssmb.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/cifssmb.c')
-rw-r--r--fs/cifs/cifssmb.c135
1 files changed, 87 insertions, 48 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 2f6795e524d3..df959bae6728 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -136,18 +136,15 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
136 } 136 }
137 } 137 }
138 138
139 if (ses->status == CifsExiting)
140 return -EIO;
141
142 /* 139 /*
143 * Give demultiplex thread up to 10 seconds to reconnect, should be 140 * Give demultiplex thread up to 10 seconds to reconnect, should be
144 * greater than cifs socket timeout which is 7 seconds 141 * greater than cifs socket timeout which is 7 seconds
145 */ 142 */
146 while (server->tcpStatus == CifsNeedReconnect) { 143 while (server->tcpStatus == CifsNeedReconnect) {
147 wait_event_interruptible_timeout(server->response_q, 144 wait_event_interruptible_timeout(server->response_q,
148 (server->tcpStatus == CifsGood), 10 * HZ); 145 (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
149 146
150 /* is TCP session is reestablished now ?*/ 147 /* are we still trying to reconnect? */
151 if (server->tcpStatus != CifsNeedReconnect) 148 if (server->tcpStatus != CifsNeedReconnect)
152 break; 149 break;
153 150
@@ -156,7 +153,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
156 * retrying until process is killed or server comes 153 * retrying until process is killed or server comes
157 * back on-line 154 * back on-line
158 */ 155 */
159 if (!tcon->retry || ses->status == CifsExiting) { 156 if (!tcon->retry) {
160 cFYI(1, "gave up waiting on reconnect in smb_init"); 157 cFYI(1, "gave up waiting on reconnect in smb_init");
161 return -EHOSTDOWN; 158 return -EHOSTDOWN;
162 } 159 }
@@ -331,37 +328,35 @@ smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
331 328
332static int validate_t2(struct smb_t2_rsp *pSMB) 329static int validate_t2(struct smb_t2_rsp *pSMB)
333{ 330{
334 int rc = -EINVAL; 331 unsigned int total_size;
335 int total_size; 332
336 char *pBCC; 333 /* check for plausible wct */
334 if (pSMB->hdr.WordCount < 10)
335 goto vt2_err;
337 336
338 /* check for plausible wct, bcc and t2 data and parm sizes */
339 /* check for parm and data offset going beyond end of smb */ 337 /* check for parm and data offset going beyond end of smb */
340 if (pSMB->hdr.WordCount >= 10) { 338 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
341 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && 339 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
342 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { 340 goto vt2_err;
343 /* check that bcc is at least as big as parms + data */ 341
344 /* check that bcc is less than negotiated smb buffer */ 342 /* check that bcc is at least as big as parms + data */
345 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); 343 /* check that bcc is less than negotiated smb buffer */
346 if (total_size < 512) { 344 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
347 total_size += 345 if (total_size >= 512)
348 le16_to_cpu(pSMB->t2_rsp.DataCount); 346 goto vt2_err;
349 /* BCC le converted in SendReceive */ 347
350 pBCC = (pSMB->hdr.WordCount * 2) + 348 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
351 sizeof(struct smb_hdr) + 349 if (total_size > get_bcc(&pSMB->hdr) ||
352 (char *)pSMB; 350 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
353 if ((total_size <= (*(u16 *)pBCC)) && 351 goto vt2_err;
354 (total_size < 352
355 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { 353 return 0;
356 return 0; 354vt2_err:
357 }
358 }
359 }
360 }
361 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, 355 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
362 sizeof(struct smb_t2_rsp) + 16); 356 sizeof(struct smb_t2_rsp) + 16);
363 return rc; 357 return -EINVAL;
364} 358}
359
365int 360int
366CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) 361CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
367{ 362{
@@ -452,7 +447,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
452 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 447 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
453 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 448 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
454 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 449 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
455 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
456 /* even though we do not use raw we might as well set this 450 /* even though we do not use raw we might as well set this
457 accurately, in case we ever find a need for it */ 451 accurately, in case we ever find a need for it */
458 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 452 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
@@ -566,7 +560,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
566 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 560 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
567 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 561 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
568 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); 562 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
569 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
570 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 563 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
571 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); 564 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
572 server->timeAdj *= 60; 565 server->timeAdj *= 60;
@@ -706,6 +699,53 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
706 return rc; 699 return rc;
707} 700}
708 701
702/*
703 * This is a no-op for now. We're not really interested in the reply, but
704 * rather in the fact that the server sent one and that server->lstrp
705 * gets updated.
706 *
707 * FIXME: maybe we should consider checking that the reply matches request?
708 */
709static void
710cifs_echo_callback(struct mid_q_entry *mid)
711{
712 struct TCP_Server_Info *server = mid->callback_data;
713
714 DeleteMidQEntry(mid);
715 atomic_dec(&server->inFlight);
716 wake_up(&server->request_q);
717}
718
719int
720CIFSSMBEcho(struct TCP_Server_Info *server)
721{
722 ECHO_REQ *smb;
723 int rc = 0;
724
725 cFYI(1, "In echo request");
726
727 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
728 if (rc)
729 return rc;
730
731 /* set up echo request */
732 smb->hdr.Tid = 0xffff;
733 smb->hdr.WordCount = 1;
734 put_unaligned_le16(1, &smb->EchoCount);
735 put_bcc_le(1, &smb->hdr);
736 smb->Data[0] = 'a';
737 smb->hdr.smb_buf_length += 3;
738
739 rc = cifs_call_async(server, (struct smb_hdr *)smb,
740 cifs_echo_callback, server);
741 if (rc)
742 cFYI(1, "Echo request failed: %d", rc);
743
744 cifs_small_buf_release(smb);
745
746 return rc;
747}
748
709int 749int
710CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) 750CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
711{ 751{
@@ -1193,7 +1233,7 @@ OldOpenRetry:
1193 pSMB->ByteCount = cpu_to_le16(count); 1233 pSMB->ByteCount = cpu_to_le16(count);
1194 /* long_op set to 1 to allow for oplock break timeouts */ 1234 /* long_op set to 1 to allow for oplock break timeouts */
1195 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1235 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1196 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1236 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1197 cifs_stats_inc(&tcon->num_opens); 1237 cifs_stats_inc(&tcon->num_opens);
1198 if (rc) { 1238 if (rc) {
1199 cFYI(1, "Error in Open = %d", rc); 1239 cFYI(1, "Error in Open = %d", rc);
@@ -1306,7 +1346,7 @@ openRetry:
1306 pSMB->ByteCount = cpu_to_le16(count); 1346 pSMB->ByteCount = cpu_to_le16(count);
1307 /* long_op set to 1 to allow for oplock break timeouts */ 1347 /* long_op set to 1 to allow for oplock break timeouts */
1308 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1309 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1349 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1310 cifs_stats_inc(&tcon->num_opens); 1350 cifs_stats_inc(&tcon->num_opens);
1311 if (rc) { 1351 if (rc) {
1312 cFYI(1, "Error in Open = %d", rc); 1352 cFYI(1, "Error in Open = %d", rc);
@@ -1388,7 +1428,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1388 iov[0].iov_base = (char *)pSMB; 1428 iov[0].iov_base = (char *)pSMB;
1389 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 1429 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1390 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, 1430 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1391 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); 1431 &resp_buf_type, CIFS_LOG_ERROR);
1392 cifs_stats_inc(&tcon->num_reads); 1432 cifs_stats_inc(&tcon->num_reads);
1393 pSMBr = (READ_RSP *)iov[0].iov_base; 1433 pSMBr = (READ_RSP *)iov[0].iov_base;
1394 if (rc) { 1434 if (rc) {
@@ -1663,7 +1703,8 @@ int
1663CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1703CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1664 const __u16 smb_file_id, const __u64 len, 1704 const __u16 smb_file_id, const __u64 len,
1665 const __u64 offset, const __u32 numUnlock, 1705 const __u64 offset, const __u32 numUnlock,
1666 const __u32 numLock, const __u8 lockType, const bool waitFlag) 1706 const __u32 numLock, const __u8 lockType,
1707 const bool waitFlag, const __u8 oplock_level)
1667{ 1708{
1668 int rc = 0; 1709 int rc = 0;
1669 LOCK_REQ *pSMB = NULL; 1710 LOCK_REQ *pSMB = NULL;
@@ -1691,6 +1732,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1691 pSMB->NumberOfLocks = cpu_to_le16(numLock); 1732 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1692 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); 1733 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1693 pSMB->LockType = lockType; 1734 pSMB->LockType = lockType;
1735 pSMB->OplockLevel = oplock_level;
1694 pSMB->AndXCommand = 0xFF; /* none */ 1736 pSMB->AndXCommand = 0xFF; /* none */
1695 pSMB->Fid = smb_file_id; /* netfid stays le */ 1737 pSMB->Fid = smb_file_id; /* netfid stays le */
1696 1738
@@ -1842,10 +1884,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
1842 __constant_cpu_to_le16(CIFS_WRLCK)) 1884 __constant_cpu_to_le16(CIFS_WRLCK))
1843 pLockData->fl_type = F_WRLCK; 1885 pLockData->fl_type = F_WRLCK;
1844 1886
1845 pLockData->fl_start = parm_data->start; 1887 pLockData->fl_start = le64_to_cpu(parm_data->start);
1846 pLockData->fl_end = parm_data->start + 1888 pLockData->fl_end = pLockData->fl_start +
1847 parm_data->length - 1; 1889 le64_to_cpu(parm_data->length) - 1;
1848 pLockData->fl_pid = parm_data->pid; 1890 pLockData->fl_pid = le32_to_cpu(parm_data->pid);
1849 } 1891 }
1850 } 1892 }
1851 1893
@@ -3087,7 +3129,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3087 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 3129 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3088 3130
3089 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 3131 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3090 CIFS_STD_OP); 3132 0);
3091 cifs_stats_inc(&tcon->num_acl_get); 3133 cifs_stats_inc(&tcon->num_acl_get);
3092 if (rc) { 3134 if (rc) {
3093 cFYI(1, "Send error in QuerySecDesc = %d", rc); 3135 cFYI(1, "Send error in QuerySecDesc = %d", rc);
@@ -4869,7 +4911,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4869 __u16 fid, __u32 pid_of_opener, bool SetAllocation) 4911 __u16 fid, __u32 pid_of_opener, bool SetAllocation)
4870{ 4912{
4871 struct smb_com_transaction2_sfi_req *pSMB = NULL; 4913 struct smb_com_transaction2_sfi_req *pSMB = NULL;
4872 char *data_offset;
4873 struct file_end_of_file_info *parm_data; 4914 struct file_end_of_file_info *parm_data;
4874 int rc = 0; 4915 int rc = 0;
4875 __u16 params, param_offset, offset, byte_count, count; 4916 __u16 params, param_offset, offset, byte_count, count;
@@ -4893,8 +4934,6 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
4893 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; 4934 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
4894 offset = param_offset + params; 4935 offset = param_offset + params;
4895 4936
4896 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4897
4898 count = sizeof(struct file_end_of_file_info); 4937 count = sizeof(struct file_end_of_file_info);
4899 pSMB->MaxParameterCount = cpu_to_le16(2); 4938 pSMB->MaxParameterCount = cpu_to_le16(2);
4900 /* BB find exact max SMB PDU from sess structure BB */ 4939 /* BB find exact max SMB PDU from sess structure BB */
@@ -5208,7 +5247,7 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset,
5208 * Samba server ignores set of file size to zero due to bugs in some 5247 * Samba server ignores set of file size to zero due to bugs in some
5209 * older clients, but we should be precise - we use SetFileSize to 5248 * older clients, but we should be precise - we use SetFileSize to
5210 * set file size and do not want to truncate file size to zero 5249 * set file size and do not want to truncate file size to zero
5211 * accidently as happened on one Samba server beta by putting 5250 * accidentally as happened on one Samba server beta by putting
5212 * zero instead of -1 here 5251 * zero instead of -1 here
5213 */ 5252 */
5214 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64); 5253 data_offset->EndOfFile = cpu_to_le64(NO_CHANGE_64);
@@ -5562,7 +5601,7 @@ QAllEAsRetry:
5562 } 5601 }
5563 5602
5564 /* make sure list_len doesn't go past end of SMB */ 5603 /* make sure list_len doesn't go past end of SMB */
5565 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); 5604 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5566 if ((char *)ea_response_data + list_len > end_of_smb) { 5605 if ((char *)ea_response_data + list_len > end_of_smb) {
5567 cFYI(1, "EA list appears to go beyond SMB"); 5606 cFYI(1, "EA list appears to go beyond SMB");
5568 rc = -EIO; 5607 rc = -EIO;