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.c118
1 files changed, 80 insertions, 38 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 67acfb3acad2..3106f5e5c633 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -331,37 +331,35 @@ smb_init_no_reconnect(int smb_command, int wct, struct cifsTconInfo *tcon,
331 331
332static int validate_t2(struct smb_t2_rsp *pSMB) 332static int validate_t2(struct smb_t2_rsp *pSMB)
333{ 333{
334 int rc = -EINVAL; 334 unsigned int total_size;
335 int total_size; 335
336 char *pBCC; 336 /* check for plausible wct */
337 if (pSMB->hdr.WordCount < 10)
338 goto vt2_err;
337 339
338 /* check for plausible wct, bcc and t2 data and parm sizes */
339 /* check for parm and data offset going beyond end of smb */ 340 /* check for parm and data offset going beyond end of smb */
340 if (pSMB->hdr.WordCount >= 10) { 341 if (get_unaligned_le16(&pSMB->t2_rsp.ParameterOffset) > 1024 ||
341 if ((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) && 342 get_unaligned_le16(&pSMB->t2_rsp.DataOffset) > 1024)
342 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) { 343 goto vt2_err;
343 /* check that bcc is at least as big as parms + data */ 344
344 /* check that bcc is less than negotiated smb buffer */ 345 /* check that bcc is at least as big as parms + data */
345 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount); 346 /* check that bcc is less than negotiated smb buffer */
346 if (total_size < 512) { 347 total_size = get_unaligned_le16(&pSMB->t2_rsp.ParameterCount);
347 total_size += 348 if (total_size >= 512)
348 le16_to_cpu(pSMB->t2_rsp.DataCount); 349 goto vt2_err;
349 /* BCC le converted in SendReceive */ 350
350 pBCC = (pSMB->hdr.WordCount * 2) + 351 total_size += get_unaligned_le16(&pSMB->t2_rsp.DataCount);
351 sizeof(struct smb_hdr) + 352 if (total_size > get_bcc(&pSMB->hdr) ||
352 (char *)pSMB; 353 total_size >= CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
353 if ((total_size <= (*(u16 *)pBCC)) && 354 goto vt2_err;
354 (total_size < 355
355 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) { 356 return 0;
356 return 0; 357vt2_err:
357 }
358 }
359 }
360 }
361 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB, 358 cifs_dump_mem("Invalid transact2 SMB: ", (char *)pSMB,
362 sizeof(struct smb_t2_rsp) + 16); 359 sizeof(struct smb_t2_rsp) + 16);
363 return rc; 360 return -EINVAL;
364} 361}
362
365int 363int
366CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) 364CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
367{ 365{
@@ -401,15 +399,12 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
401 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { 399 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) {
402 cFYI(1, "Kerberos only mechanism, enable extended security"); 400 cFYI(1, "Kerberos only mechanism, enable extended security");
403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 401 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
404 } 402 } else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
405#ifdef CONFIG_CIFS_EXPERIMENTAL
406 else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
407 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 403 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
408 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { 404 else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
409 cFYI(1, "NTLMSSP only mechanism, enable extended security"); 405 cFYI(1, "NTLMSSP only mechanism, enable extended security");
410 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; 406 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
411 } 407 }
412#endif
413 408
414 count = 0; 409 count = 0;
415 for (i = 0; i < CIFS_NUM_PROT; i++) { 410 for (i = 0; i < CIFS_NUM_PROT; i++) {
@@ -455,7 +450,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
455 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), 450 server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
456 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 451 (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
457 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); 452 server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
458 GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
459 /* even though we do not use raw we might as well set this 453 /* even though we do not use raw we might as well set this
460 accurately, in case we ever find a need for it */ 454 accurately, in case we ever find a need for it */
461 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) { 455 if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
@@ -569,7 +563,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
569 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); 563 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
570 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); 564 server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
571 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); 565 cFYI(DBG2, "Max buf = %d", ses->server->maxBuf);
572 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
573 server->capabilities = le32_to_cpu(pSMBr->Capabilities); 566 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
574 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); 567 server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone);
575 server->timeAdj *= 60; 568 server->timeAdj *= 60;
@@ -709,6 +702,53 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
709 return rc; 702 return rc;
710} 703}
711 704
705/*
706 * This is a no-op for now. We're not really interested in the reply, but
707 * rather in the fact that the server sent one and that server->lstrp
708 * gets updated.
709 *
710 * FIXME: maybe we should consider checking that the reply matches request?
711 */
712static void
713cifs_echo_callback(struct mid_q_entry *mid)
714{
715 struct TCP_Server_Info *server = mid->callback_data;
716
717 DeleteMidQEntry(mid);
718 atomic_dec(&server->inFlight);
719 wake_up(&server->request_q);
720}
721
722int
723CIFSSMBEcho(struct TCP_Server_Info *server)
724{
725 ECHO_REQ *smb;
726 int rc = 0;
727
728 cFYI(1, "In echo request");
729
730 rc = small_smb_init(SMB_COM_ECHO, 0, NULL, (void **)&smb);
731 if (rc)
732 return rc;
733
734 /* set up echo request */
735 smb->hdr.Tid = cpu_to_le16(0xffff);
736 smb->hdr.WordCount = 1;
737 put_unaligned_le16(1, &smb->EchoCount);
738 put_bcc_le(1, &smb->hdr);
739 smb->Data[0] = 'a';
740 smb->hdr.smb_buf_length += 3;
741
742 rc = cifs_call_async(server, (struct smb_hdr *)smb,
743 cifs_echo_callback, server);
744 if (rc)
745 cFYI(1, "Echo request failed: %d", rc);
746
747 cifs_small_buf_release(smb);
748
749 return rc;
750}
751
712int 752int
713CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) 753CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
714{ 754{
@@ -1196,7 +1236,7 @@ OldOpenRetry:
1196 pSMB->ByteCount = cpu_to_le16(count); 1236 pSMB->ByteCount = cpu_to_le16(count);
1197 /* long_op set to 1 to allow for oplock break timeouts */ 1237 /* long_op set to 1 to allow for oplock break timeouts */
1198 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1238 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1199 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1239 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1200 cifs_stats_inc(&tcon->num_opens); 1240 cifs_stats_inc(&tcon->num_opens);
1201 if (rc) { 1241 if (rc) {
1202 cFYI(1, "Error in Open = %d", rc); 1242 cFYI(1, "Error in Open = %d", rc);
@@ -1309,7 +1349,7 @@ openRetry:
1309 pSMB->ByteCount = cpu_to_le16(count); 1349 pSMB->ByteCount = cpu_to_le16(count);
1310 /* long_op set to 1 to allow for oplock break timeouts */ 1350 /* long_op set to 1 to allow for oplock break timeouts */
1311 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1351 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1312 (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); 1352 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1313 cifs_stats_inc(&tcon->num_opens); 1353 cifs_stats_inc(&tcon->num_opens);
1314 if (rc) { 1354 if (rc) {
1315 cFYI(1, "Error in Open = %d", rc); 1355 cFYI(1, "Error in Open = %d", rc);
@@ -1391,7 +1431,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1391 iov[0].iov_base = (char *)pSMB; 1431 iov[0].iov_base = (char *)pSMB;
1392 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 1432 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
1393 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */, 1433 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovecs */,
1394 &resp_buf_type, CIFS_STD_OP | CIFS_LOG_ERROR); 1434 &resp_buf_type, CIFS_LOG_ERROR);
1395 cifs_stats_inc(&tcon->num_reads); 1435 cifs_stats_inc(&tcon->num_reads);
1396 pSMBr = (READ_RSP *)iov[0].iov_base; 1436 pSMBr = (READ_RSP *)iov[0].iov_base;
1397 if (rc) { 1437 if (rc) {
@@ -1666,7 +1706,8 @@ int
1666CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, 1706CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1667 const __u16 smb_file_id, const __u64 len, 1707 const __u16 smb_file_id, const __u64 len,
1668 const __u64 offset, const __u32 numUnlock, 1708 const __u64 offset, const __u32 numUnlock,
1669 const __u32 numLock, const __u8 lockType, const bool waitFlag) 1709 const __u32 numLock, const __u8 lockType,
1710 const bool waitFlag, const __u8 oplock_level)
1670{ 1711{
1671 int rc = 0; 1712 int rc = 0;
1672 LOCK_REQ *pSMB = NULL; 1713 LOCK_REQ *pSMB = NULL;
@@ -1694,6 +1735,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1694 pSMB->NumberOfLocks = cpu_to_le16(numLock); 1735 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1695 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock); 1736 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1696 pSMB->LockType = lockType; 1737 pSMB->LockType = lockType;
1738 pSMB->OplockLevel = oplock_level;
1697 pSMB->AndXCommand = 0xFF; /* none */ 1739 pSMB->AndXCommand = 0xFF; /* none */
1698 pSMB->Fid = smb_file_id; /* netfid stays le */ 1740 pSMB->Fid = smb_file_id; /* netfid stays le */
1699 1741
@@ -3090,7 +3132,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
3090 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4; 3132 iov[0].iov_len = pSMB->hdr.smb_buf_length + 4;
3091 3133
3092 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type, 3134 rc = SendReceive2(xid, tcon->ses, iov, 1 /* num iovec */, &buf_type,
3093 CIFS_STD_OP); 3135 0);
3094 cifs_stats_inc(&tcon->num_acl_get); 3136 cifs_stats_inc(&tcon->num_acl_get);
3095 if (rc) { 3137 if (rc) {
3096 cFYI(1, "Send error in QuerySecDesc = %d", rc); 3138 cFYI(1, "Send error in QuerySecDesc = %d", rc);
@@ -5565,7 +5607,7 @@ QAllEAsRetry:
5565 } 5607 }
5566 5608
5567 /* make sure list_len doesn't go past end of SMB */ 5609 /* make sure list_len doesn't go past end of SMB */
5568 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); 5610 end_of_smb = (char *)pByteArea(&pSMBr->hdr) + get_bcc(&pSMBr->hdr);
5569 if ((char *)ea_response_data + list_len > end_of_smb) { 5611 if ((char *)ea_response_data + list_len > end_of_smb) {
5570 cFYI(1, "EA list appears to go beyond SMB"); 5612 cFYI(1, "EA list appears to go beyond SMB");
5571 rc = -EIO; 5613 rc = -EIO;