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
select CRYPTO
select CRYPTO_MD4
select CRYPTO_MD5
select CRYPTO_SHA256
select CRYPTO_CMAC
select CRYPTO_HMAC
select CRYPTO_ARC4
select CRYPTO_AEAD2
select CRYPTO_CCM
select CRYPTO_ECB
select CRYPTO_AES
select CRYPTO_DES
help
This is the client VFS module for the SMB3 family of NAS protocols,
......
......@@ -661,7 +661,9 @@ struct TCP_Server_Info {
#endif
unsigned int max_read;
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 mutex reconnect_mutex; /* prevent simultaneous reconnects */
unsigned long echo_interval;
......@@ -849,7 +851,9 @@ struct cifs_ses {
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
__u8 smb3encryptionkey[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
......
......@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
{STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"},
{STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
{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_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
{STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
......
......@@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct cifs_fid fid;
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);
if (!utf16_path)
......@@ -541,14 +542,32 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL);
if (smb2_data == NULL) {
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
return -ENOMEM;
while (1) {
smb2_data = kzalloc(ea_buf_size, GFP_KERNEL);
if (smb2_data == NULL) {
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);
if (!rc)
......
......@@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
{
int rc = 0;
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 inbuflen; /* max of 4 dialects */
......@@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
rsplen);
/* relax check since Mac returns max bufsize allowed on ioctl */
if (rsplen > CIFSMaxBufSize)
return -EIO;
if ((rsplen > CIFSMaxBufSize)
|| (rsplen < sizeof(struct validate_negotiate_info_rsp)))
goto err_rsp_free;
}
/* 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 */
cifs_dbg(FYI, "validate negotiate info successful\n");
kfree(pneg_rsp);
return 0;
vneg_out:
cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
err_rsp_free:
kfree(pneg_rsp);
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_rsp *rsp = NULL;
struct kvec iov[2];
struct kvec rsp_iov;
struct kvec rsp_iov = { NULL, 0 };
int rc = 0;
int resp_buftype;
int unc_path_len;
......@@ -1372,7 +1376,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
return rc;
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);
}
goto tcon_exit;
......@@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
} else
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);
cifs_small_buf_release(req);
......@@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
req->PersistentFileId = persistent_fid;
req->VolatileFileId = volatile_fid;
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);
iov[0].iov_base = (char *)req;
......@@ -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,
u64 persistent_fid, u64 volatile_fid,
struct smb2_file_full_ea_info *data)
u64 persistent_fid, u64 volatile_fid,
int ea_buf_size, struct smb2_file_full_ea_info *data)
{
return query_info(xid, tcon, persistent_fid, volatile_fid,
FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0,
SMB2_MAX_EA_BUF,
ea_buf_size,
sizeof(struct smb2_file_full_ea_info),
(void **)&data,
NULL);
......
......@@ -832,7 +832,7 @@ struct smb2_flush_rsp {
/* Channel field for read and write: exactly one of following flags can be set*/
#define SMB2_CHANNEL_NONE 0x00000000
#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 */
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 */
} __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 */
__le32 next_entry_offset;
......
......@@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id);
extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
int ea_buf_size,
struct smb2_file_full_ea_info *data);
extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
......
......@@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses)
return generate_smb3signingkey(ses, &triplet);
}
#ifdef CONFIG_CIFS_SMB311
int
generate_smb311signingkey(struct cifs_ses *ses)
......@@ -398,25 +399,26 @@ generate_smb311signingkey(struct cifs_ses *ses)
struct derivation *d;
d = &triplet.signing;
d->label.iov_base = "SMB2AESCMAC";
d->label.iov_len = 12;
d->context.iov_base = "SmbSign";
d->context.iov_len = 8;
d->label.iov_base = "SMBSigningKey";
d->label.iov_len = 14;
d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 64;
d = &triplet.encryption;
d->label.iov_base = "SMB2AESCCM";
d->label.iov_len = 11;
d->context.iov_base = "ServerIn ";
d->context.iov_len = 10;
d->label.iov_base = "SMBC2SCipherKey";
d->label.iov_len = 16;
d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 64;
d = &triplet.decryption;
d->label.iov_base = "SMB2AESCCM";
d->label.iov_len = 11;
d->context.iov_base = "ServerOut";
d->context.iov_len = 10;
d->label.iov_base = "SMBS2CCipherKey";
d->label.iov_len = 16;
d->context.iov_base = ses->preauth_sha_hash;
d->context.iov_len = 64;
return generate_smb3signingkey(ses, &triplet);
}
#endif /* 311 */
int
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