mirror of https://gitee.com/openkylin/linux.git
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:
commit
7814023404
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue