Various SMB3 fixes for 4.14 and stable

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQGcBAABAgAGBQJZ81hKAAoJEIosvXAHck9R7K4L/R4vPpYn19s/xPUf0fUYMOWO
 JOIghfeCmmfCd2kTZF+fcDRNBpGnJjjs4ZPloxIbF7bQF0VbjrkToxthF6f9aYIJ
 gt0jH1ntGUvraDpkZelTAGRj1BZou2IBzJF3Or1sL83ZX76fyXm9cJUx8Y+l2Mlx
 BJMOL0Au38oRKOGnGk3GPtrflgNxe+6cTpNhLmVa9CBNDMQYjobrALgGPpbGf5h3
 6l1i0IxMXuxeXjqFva0GKCjTsQSON44gNNHQoggIfHvE3nBVpSZLCwNwrVHOfd8q
 4FlEXPzr3ME4WzASWqw1kAX+aij2NqbaLgDs7USkn4mUheIvZcHhC0LPVZJrZ1b4
 2c3RHkOV0aZQunPJyq5vtO9B4TJC6MLcHS46iwQ6lao9hTVT8OqV7R40qmzQyt06
 KwdIGObEm76J7u4lgVlAsapVKgPLOPuObQKhYUdNvRarorNaxgtadnHOhXM20G3S
 PE23XvNJYwKl6SJbP97ih8Uq0//7vNCxd/khdnq4FQ==
 =8LHe
 -----END PGP SIGNATURE-----

Merge tag '4.14-smb3-fixes-for-stable' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Various SMB3 fixes for 4.14 and stable"

* tag '4.14-smb3-fixes-for-stable' of git://git.samba.org/sfrench/cifs-2.6:
  SMB3: Validate negotiate request must always be signed
  SMB: fix validate negotiate info uninitialised memory use
  SMB: fix leak of validate negotiate info response buffer
  CIFS: Fix NULL pointer deref on SMB2_tcon() failure
  CIFS: do not send invalid input buffer on QUERY_INFO requests
  cifs: Select all required crypto modules
  CIFS: SMBD: Fix the definition for SMB2_CHANNEL_RDMA_V1_INVALIDATE
  cifs: handle large EA requests more gracefully in smb2+
  Fix encryption labels and lengths for SMB3.1.1
This commit is contained in:
Linus Torvalds 2017-10-28 08:39:35 -07:00
commit 7814023404
8 changed files with 77 additions and 34 deletions

View File

@ -5,9 +5,14 @@ config CIFS
select CRYPTO select CRYPTO
select CRYPTO_MD4 select CRYPTO_MD4
select CRYPTO_MD5 select CRYPTO_MD5
select CRYPTO_SHA256
select CRYPTO_CMAC
select CRYPTO_HMAC select CRYPTO_HMAC
select CRYPTO_ARC4 select CRYPTO_ARC4
select CRYPTO_AEAD2
select CRYPTO_CCM
select CRYPTO_ECB select CRYPTO_ECB
select CRYPTO_AES
select CRYPTO_DES select CRYPTO_DES
help help
This is the client VFS module for the SMB3 family of NAS protocols, This is the client VFS module for the SMB3 family of NAS protocols,

View File

@ -661,7 +661,9 @@ struct TCP_Server_Info {
#endif #endif
unsigned int max_read; unsigned int max_read;
unsigned int max_write; unsigned int max_write;
__u8 preauth_hash[512]; #ifdef CONFIG_CIFS_SMB311
__u8 preauth_sha_hash[64]; /* save initital negprot hash */
#endif /* 3.1.1 */
struct delayed_work reconnect; /* reconnect workqueue job */ struct delayed_work reconnect; /* reconnect workqueue job */
struct mutex reconnect_mutex; /* prevent simultaneous reconnects */ struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
unsigned long echo_interval; unsigned long echo_interval;
@ -849,7 +851,9 @@ struct cifs_ses {
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
__u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
__u8 preauth_hash[512]; #ifdef CONFIG_CIFS_SMB311
__u8 preauth_sha_hash[64];
#endif /* 3.1.1 */
}; };
static inline bool static inline bool

View File

@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
{STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"}, {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"},
{STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"}, {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
{STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"}, {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
{STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"}, {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"},
{STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"}, {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
{STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"}, {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
{STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"}, {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},

View File

@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms; struct cifs_open_parms oparms;
struct cifs_fid fid; struct cifs_fid fid;
struct smb2_file_full_ea_info *smb2_data; struct smb2_file_full_ea_info *smb2_data;
int ea_buf_size = SMB2_MIN_EA_BUF;
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
if (!utf16_path) if (!utf16_path)
@ -541,14 +542,32 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL); while (1) {
if (smb2_data == NULL) { smb2_data = kzalloc(ea_buf_size, GFP_KERNEL);
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); if (smb2_data == NULL) {
return -ENOMEM; SMB2_close(xid, tcon, fid.persistent_fid,
fid.volatile_fid);
return -ENOMEM;
}
rc = SMB2_query_eas(xid, tcon, fid.persistent_fid,
fid.volatile_fid,
ea_buf_size, smb2_data);
if (rc != -E2BIG)
break;
kfree(smb2_data);
ea_buf_size <<= 1;
if (ea_buf_size > SMB2_MAX_EA_BUF) {
cifs_dbg(VFS, "EA size is too large\n");
SMB2_close(xid, tcon, fid.persistent_fid,
fid.volatile_fid);
return -ENOMEM;
}
} }
rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, fid.volatile_fid,
smb2_data);
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
if (!rc) if (!rc)

View File

@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
{ {
int rc = 0; int rc = 0;
struct validate_negotiate_info_req vneg_inbuf; struct validate_negotiate_info_req vneg_inbuf;
struct validate_negotiate_info_rsp *pneg_rsp; struct validate_negotiate_info_rsp *pneg_rsp = NULL;
u32 rsplen; u32 rsplen;
u32 inbuflen; /* max of 4 dialects */ u32 inbuflen; /* max of 4 dialects */
@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
rsplen); rsplen);
/* relax check since Mac returns max bufsize allowed on ioctl */ /* relax check since Mac returns max bufsize allowed on ioctl */
if (rsplen > CIFSMaxBufSize) if ((rsplen > CIFSMaxBufSize)
return -EIO; || (rsplen < sizeof(struct validate_negotiate_info_rsp)))
goto err_rsp_free;
} }
/* check validate negotiate info response matches what we got earlier */ /* check validate negotiate info response matches what we got earlier */
@ -747,10 +748,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
/* validate negotiate successful */ /* validate negotiate successful */
cifs_dbg(FYI, "validate negotiate info successful\n"); cifs_dbg(FYI, "validate negotiate info successful\n");
kfree(pneg_rsp);
return 0; return 0;
vneg_out: vneg_out:
cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
err_rsp_free:
kfree(pneg_rsp);
return -EIO; return -EIO;
} }
@ -1255,7 +1259,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
struct smb2_tree_connect_req *req; struct smb2_tree_connect_req *req;
struct smb2_tree_connect_rsp *rsp = NULL; struct smb2_tree_connect_rsp *rsp = NULL;
struct kvec iov[2]; struct kvec iov[2];
struct kvec rsp_iov; struct kvec rsp_iov = { NULL, 0 };
int rc = 0; int rc = 0;
int resp_buftype; int resp_buftype;
int unc_path_len; int unc_path_len;
@ -1372,7 +1376,7 @@ tcon_exit:
return rc; return rc;
tcon_error_exit: tcon_error_exit:
if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) { if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
} }
goto tcon_exit; goto tcon_exit;
@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
} else } else
iov[0].iov_len = get_rfc1002_length(req) + 4; iov[0].iov_len = get_rfc1002_length(req) + 4;
/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov); rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req); cifs_small_buf_release(req);
@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
req->PersistentFileId = persistent_fid; req->PersistentFileId = persistent_fid;
req->VolatileFileId = volatile_fid; req->VolatileFileId = volatile_fid;
req->AdditionalInformation = cpu_to_le32(additional_info); req->AdditionalInformation = cpu_to_le32(additional_info);
/* 4 for rfc1002 length field and 1 for Buffer */
req->InputBufferOffset = /*
cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4); * We do not use the input buffer (do not send extra byte)
*/
req->InputBufferOffset = 0;
inc_rfc1001_len(req, -1);
req->OutputBufferLength = cpu_to_le32(output_len); req->OutputBufferLength = cpu_to_le32(output_len);
iov[0].iov_base = (char *)req; iov[0].iov_base = (char *)req;
@ -2233,12 +2244,12 @@ qinf_exit:
} }
int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u64 persistent_fid, u64 volatile_fid,
struct smb2_file_full_ea_info *data) int ea_buf_size, struct smb2_file_full_ea_info *data)
{ {
return query_info(xid, tcon, persistent_fid, volatile_fid, return query_info(xid, tcon, persistent_fid, volatile_fid,
FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0,
SMB2_MAX_EA_BUF, ea_buf_size,
sizeof(struct smb2_file_full_ea_info), sizeof(struct smb2_file_full_ea_info),
(void **)&data, (void **)&data,
NULL); NULL);

View File

@ -832,7 +832,7 @@ struct smb2_flush_rsp {
/* Channel field for read and write: exactly one of following flags can be set*/ /* Channel field for read and write: exactly one of following flags can be set*/
#define SMB2_CHANNEL_NONE 0x00000000 #define SMB2_CHANNEL_NONE 0x00000000
#define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */ #define SMB2_CHANNEL_RDMA_V1 0x00000001 /* SMB3 or later */
#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */ #define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002 /* SMB3.02 or later */
/* SMB2 read request without RFC1001 length at the beginning */ /* SMB2 read request without RFC1001 length at the beginning */
struct smb2_read_plain_req { struct smb2_read_plain_req {
@ -1178,7 +1178,8 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
char FileName[0]; /* Name to be assigned to new link */ char FileName[0]; /* Name to be assigned to new link */
} __packed; /* level 11 Set */ } __packed; /* level 11 Set */
#define SMB2_MAX_EA_BUF 2048 #define SMB2_MIN_EA_BUF 2048
#define SMB2_MAX_EA_BUF 65536
struct smb2_file_full_ea_info { /* encoding of response for level 15 */ struct smb2_file_full_ea_info { /* encoding of response for level 15 */
__le32 next_entry_offset; __le32 next_entry_offset;

View File

@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id); u64 persistent_file_id, u64 volatile_file_id);
extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id, u64 persistent_file_id, u64 volatile_file_id,
int ea_buf_size,
struct smb2_file_full_ea_info *data); struct smb2_file_full_ea_info *data);
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id, u64 persistent_file_id, u64 volatile_file_id,

View File

@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses)
return generate_smb3signingkey(ses, &triplet); return generate_smb3signingkey(ses, &triplet);
} }
#ifdef CONFIG_CIFS_SMB311
int int
generate_smb311signingkey(struct cifs_ses *ses) generate_smb311signingkey(struct cifs_ses *ses)
@ -398,25 +399,26 @@ generate_smb311signingkey(struct cifs_ses *ses)
struct derivation *d; struct derivation *d;
d = &triplet.signing; d = &triplet.signing;
d->label.iov_base = "SMB2AESCMAC"; d->label.iov_base = "SMBSigningKey";
d->label.iov_len = 12; d->label.iov_len = 14;
d->context.iov_base = "SmbSign"; d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 8; d->context.iov_len = 64;
d = &triplet.encryption; d = &triplet.encryption;
d->label.iov_base = "SMB2AESCCM"; d->label.iov_base = "SMBC2SCipherKey";
d->label.iov_len = 11; d->label.iov_len = 16;
d->context.iov_base = "ServerIn "; d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 10; d->context.iov_len = 64;
d = &triplet.decryption; d = &triplet.decryption;
d->label.iov_base = "SMB2AESCCM"; d->label.iov_base = "SMBS2CCipherKey";
d->label.iov_len = 11; d->label.iov_len = 16;
d->context.iov_base = "ServerOut"; d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 10; d->context.iov_len = 64;
return generate_smb3signingkey(ses, &triplet); return generate_smb3signingkey(ses, &triplet);
} }
#endif /* 311 */
int int
smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)