Commit 78140234 authored by Linus Torvalds's avatar Linus Torvalds

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
parents c9f27f9f 4587eee0
...@@ -5,9 +5,14 @@ config CIFS ...@@ -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,
......
...@@ -661,7 +661,9 @@ struct TCP_Server_Info { ...@@ -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 { ...@@ -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
......
...@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = { ...@@ -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"},
......
...@@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -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, ...@@ -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)
......
...@@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1372,7 +1376,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
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, ...@@ -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, ...@@ -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 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2233,12 +2244,12 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
} }
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);
......
...@@ -832,7 +832,7 @@ struct smb2_flush_rsp { ...@@ -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 */ ...@@ -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;
......
...@@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -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,
......
...@@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses) ...@@ -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) ...@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment