diff options
| -rw-r--r-- | fs/cifs/connect.c | 2 | ||||
| -rw-r--r-- | fs/cifs/smb2ops.c | 4 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.c | 40 | ||||
| -rw-r--r-- | fs/cifs/smb2pdu.h | 2 |
4 files changed, 32 insertions, 16 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 69b9d5606eba..f66529679ca2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -483,7 +483,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 483 | cifs_sb = NULL; | 483 | cifs_sb = NULL; |
| 484 | } else { | 484 | } else { |
| 485 | rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); | 485 | rc = reconn_setup_dfs_targets(cifs_sb, &tgt_list, &tgt_it); |
| 486 | if (rc) { | 486 | if (rc && (rc != -EOPNOTSUPP)) { |
| 487 | cifs_dbg(VFS, "%s: no target servers for DFS failover\n", | 487 | cifs_dbg(VFS, "%s: no target servers for DFS failover\n", |
| 488 | __func__); | 488 | __func__); |
| 489 | } else { | 489 | } else { |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 33100ef74d7f..cf7eb891804f 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -3472,8 +3472,10 @@ smb3_receive_transform(struct TCP_Server_Info *server, | |||
| 3472 | } | 3472 | } |
| 3473 | 3473 | ||
| 3474 | /* TODO: add support for compounds containing READ. */ | 3474 | /* TODO: add support for compounds containing READ. */ |
| 3475 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) | 3475 | if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) { |
| 3476 | *num_mids = 1; | ||
| 3476 | return receive_encrypted_read(server, &mids[0]); | 3477 | return receive_encrypted_read(server, &mids[0]); |
| 3478 | } | ||
| 3477 | 3479 | ||
| 3478 | return receive_encrypted_standard(server, mids, bufs, num_mids); | 3480 | return receive_encrypted_standard(server, mids, bufs, num_mids); |
| 3479 | } | 3481 | } |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index e283590955cd..e57f6aa1d638 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -451,10 +451,6 @@ smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon, | |||
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | 453 | ||
| 454 | /* offset is sizeof smb2_negotiate_req but rounded up to 8 bytes */ | ||
| 455 | #define OFFSET_OF_NEG_CONTEXT 0x68 /* sizeof(struct smb2_negotiate_req) */ | ||
| 456 | |||
| 457 | |||
| 458 | #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) | 454 | #define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1) |
| 459 | #define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) | 455 | #define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2) |
| 460 | #define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100) | 456 | #define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100) |
| @@ -491,10 +487,24 @@ static void | |||
| 491 | assemble_neg_contexts(struct smb2_negotiate_req *req, | 487 | assemble_neg_contexts(struct smb2_negotiate_req *req, |
| 492 | unsigned int *total_len) | 488 | unsigned int *total_len) |
| 493 | { | 489 | { |
| 494 | char *pneg_ctxt = (char *)req + OFFSET_OF_NEG_CONTEXT; | 490 | char *pneg_ctxt = (char *)req; |
| 495 | unsigned int ctxt_len; | 491 | unsigned int ctxt_len; |
| 496 | 492 | ||
| 497 | *total_len += 2; /* Add 2 due to round to 8 byte boundary for 1st ctxt */ | 493 | if (*total_len > 200) { |
| 494 | /* In case length corrupted don't want to overrun smb buffer */ | ||
| 495 | cifs_dbg(VFS, "Bad frame length assembling neg contexts\n"); | ||
| 496 | return; | ||
| 497 | } | ||
| 498 | |||
| 499 | /* | ||
| 500 | * round up total_len of fixed part of SMB3 negotiate request to 8 | ||
| 501 | * byte boundary before adding negotiate contexts | ||
| 502 | */ | ||
| 503 | *total_len = roundup(*total_len, 8); | ||
| 504 | |||
| 505 | pneg_ctxt = (*total_len) + (char *)req; | ||
| 506 | req->NegotiateContextOffset = cpu_to_le32(*total_len); | ||
| 507 | |||
| 498 | build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); | 508 | build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt); |
| 499 | ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; | 509 | ctxt_len = DIV_ROUND_UP(sizeof(struct smb2_preauth_neg_context), 8) * 8; |
| 500 | *total_len += ctxt_len; | 510 | *total_len += ctxt_len; |
| @@ -508,7 +518,6 @@ assemble_neg_contexts(struct smb2_negotiate_req *req, | |||
| 508 | build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); | 518 | build_posix_ctxt((struct smb2_posix_neg_context *)pneg_ctxt); |
| 509 | *total_len += sizeof(struct smb2_posix_neg_context); | 519 | *total_len += sizeof(struct smb2_posix_neg_context); |
| 510 | 520 | ||
| 511 | req->NegotiateContextOffset = cpu_to_le32(OFFSET_OF_NEG_CONTEXT); | ||
| 512 | req->NegotiateContextCount = cpu_to_le16(3); | 521 | req->NegotiateContextCount = cpu_to_le16(3); |
| 513 | } | 522 | } |
| 514 | 523 | ||
| @@ -724,8 +733,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 724 | req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); | 733 | req->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
| 725 | req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); | 734 | req->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
| 726 | req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); | 735 | req->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); |
| 727 | req->DialectCount = cpu_to_le16(3); | 736 | req->Dialects[3] = cpu_to_le16(SMB311_PROT_ID); |
| 728 | total_len += 6; | 737 | req->DialectCount = cpu_to_le16(4); |
| 738 | total_len += 8; | ||
| 729 | } else { | 739 | } else { |
| 730 | /* otherwise send specific dialect */ | 740 | /* otherwise send specific dialect */ |
| 731 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); | 741 | req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); |
| @@ -749,7 +759,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 749 | else { | 759 | else { |
| 750 | memcpy(req->ClientGUID, server->client_guid, | 760 | memcpy(req->ClientGUID, server->client_guid, |
| 751 | SMB2_CLIENT_GUID_SIZE); | 761 | SMB2_CLIENT_GUID_SIZE); |
| 752 | if (ses->server->vals->protocol_id == SMB311_PROT_ID) | 762 | if ((ses->server->vals->protocol_id == SMB311_PROT_ID) || |
| 763 | (strcmp(ses->server->vals->version_string, | ||
| 764 | SMBDEFAULT_VERSION_STRING) == 0)) | ||
| 753 | assemble_neg_contexts(req, &total_len); | 765 | assemble_neg_contexts(req, &total_len); |
| 754 | } | 766 | } |
| 755 | iov[0].iov_base = (char *)req; | 767 | iov[0].iov_base = (char *)req; |
| @@ -794,7 +806,8 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) | |||
| 794 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { | 806 | } else if (rsp->DialectRevision == cpu_to_le16(SMB21_PROT_ID)) { |
| 795 | /* ops set to 3.0 by default for default so update */ | 807 | /* ops set to 3.0 by default for default so update */ |
| 796 | ses->server->ops = &smb21_operations; | 808 | ses->server->ops = &smb21_operations; |
| 797 | } | 809 | } else if (rsp->DialectRevision == cpu_to_le16(SMB311_PROT_ID)) |
| 810 | ses->server->ops = &smb311_operations; | ||
| 798 | } else if (le16_to_cpu(rsp->DialectRevision) != | 811 | } else if (le16_to_cpu(rsp->DialectRevision) != |
| 799 | ses->server->vals->protocol_id) { | 812 | ses->server->vals->protocol_id) { |
| 800 | /* if requested single dialect ensure returned dialect matched */ | 813 | /* if requested single dialect ensure returned dialect matched */ |
| @@ -941,13 +954,14 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) | |||
| 941 | pneg_inbuf->DialectCount = cpu_to_le16(2); | 954 | pneg_inbuf->DialectCount = cpu_to_le16(2); |
| 942 | /* structure is big enough for 3 dialects, sending only 2 */ | 955 | /* structure is big enough for 3 dialects, sending only 2 */ |
| 943 | inbuflen = sizeof(*pneg_inbuf) - | 956 | inbuflen = sizeof(*pneg_inbuf) - |
| 944 | sizeof(pneg_inbuf->Dialects[0]); | 957 | (2 * sizeof(pneg_inbuf->Dialects[0])); |
| 945 | } else if (strcmp(tcon->ses->server->vals->version_string, | 958 | } else if (strcmp(tcon->ses->server->vals->version_string, |
| 946 | SMBDEFAULT_VERSION_STRING) == 0) { | 959 | SMBDEFAULT_VERSION_STRING) == 0) { |
| 947 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); | 960 | pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID); |
| 948 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); | 961 | pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID); |
| 949 | pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); | 962 | pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID); |
| 950 | pneg_inbuf->DialectCount = cpu_to_le16(3); | 963 | pneg_inbuf->Dialects[3] = cpu_to_le16(SMB311_PROT_ID); |
| 964 | pneg_inbuf->DialectCount = cpu_to_le16(4); | ||
| 951 | /* structure is big enough for 3 dialects */ | 965 | /* structure is big enough for 3 dialects */ |
| 952 | inbuflen = sizeof(*pneg_inbuf); | 966 | inbuflen = sizeof(*pneg_inbuf); |
| 953 | } else { | 967 | } else { |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 05dea6750c33..7a2d0a2255e6 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
| @@ -898,7 +898,7 @@ struct validate_negotiate_info_req { | |||
| 898 | __u8 Guid[SMB2_CLIENT_GUID_SIZE]; | 898 | __u8 Guid[SMB2_CLIENT_GUID_SIZE]; |
| 899 | __le16 SecurityMode; | 899 | __le16 SecurityMode; |
| 900 | __le16 DialectCount; | 900 | __le16 DialectCount; |
| 901 | __le16 Dialects[3]; /* BB expand this if autonegotiate > 3 dialects */ | 901 | __le16 Dialects[4]; /* BB expand this if autonegotiate > 4 dialects */ |
| 902 | } __packed; | 902 | } __packed; |
| 903 | 903 | ||
| 904 | struct validate_negotiate_info_rsp { | 904 | struct validate_negotiate_info_rsp { |
