Commit 81b1d39f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.12-rc4-smb3' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Five cifs/smb3 fixes, two for stable.

  Includes an important fix for encryption and an ACL fix, as well as a
  fix for possible reflink data corruption"

* tag '5.12-rc4-smb3' of git://git.samba.org/sfrench/cifs-2.6:
  smb3: fix cached file size problems in duplicate extents (reflink)
  cifs: Silently ignore unknown oplock break handle
  cifs: revalidate mapping when we open files for SMB1 POSIX
  cifs: Fix chmod with modefromsid when an older ACE already exists.
  cifs: Adjust key sizes and key generation routines for AES256 encryption
parents b44d1ddc cfc63fc8
...@@ -1130,8 +1130,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl, ...@@ -1130,8 +1130,7 @@ static int set_chmod_dacl(struct cifs_acl *pdacl, struct cifs_acl *pndacl,
} }
/* If it's any one of the ACE we're replacing, skip! */ /* If it's any one of the ACE we're replacing, skip! */
if (!mode_from_sid && if (((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
((compare_sids(&pntace->sid, &sid_unix_NFS_mode) == 0) ||
(compare_sids(&pntace->sid, pownersid) == 0) || (compare_sids(&pntace->sid, pownersid) == 0) ||
(compare_sids(&pntace->sid, pgrpsid) == 0) || (compare_sids(&pntace->sid, pgrpsid) == 0) ||
(compare_sids(&pntace->sid, &sid_everyone) == 0) || (compare_sids(&pntace->sid, &sid_everyone) == 0) ||
......
...@@ -919,8 +919,8 @@ struct cifs_ses { ...@@ -919,8 +919,8 @@ struct cifs_ses {
bool binding:1; /* are we binding the session? */ bool binding:1; /* are we binding the session? */
__u16 session_flags; __u16 session_flags;
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
__u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE]; __u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
__u8 binding_preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE]; __u8 binding_preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
......
...@@ -147,6 +147,11 @@ ...@@ -147,6 +147,11 @@
*/ */
#define SMB3_SIGN_KEY_SIZE (16) #define SMB3_SIGN_KEY_SIZE (16)
/*
* Size of the smb3 encryption/decryption keys
*/
#define SMB3_ENC_DEC_KEY_SIZE (32)
#define CIFS_CLIENT_CHALLENGE_SIZE (8) #define CIFS_CLIENT_CHALLENGE_SIZE (8)
#define CIFS_SERVER_CHALLENGE_SIZE (8) #define CIFS_SERVER_CHALLENGE_SIZE (8)
#define CIFS_HMAC_MD5_HASH_SIZE (16) #define CIFS_HMAC_MD5_HASH_SIZE (16)
......
...@@ -165,6 +165,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -165,6 +165,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
goto posix_open_ret; goto posix_open_ret;
} }
} else { } else {
cifs_revalidate_mapping(*pinode);
cifs_fattr_to_inode(*pinode, &fattr); cifs_fattr_to_inode(*pinode, &fattr);
} }
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#define SMB2_HMACSHA256_SIZE (32) #define SMB2_HMACSHA256_SIZE (32)
#define SMB2_CMACAES_SIZE (16) #define SMB2_CMACAES_SIZE (16)
#define SMB3_SIGNKEY_SIZE (16) #define SMB3_SIGNKEY_SIZE (16)
#define SMB3_GCM128_CRYPTKEY_SIZE (16)
#define SMB3_GCM256_CRYPTKEY_SIZE (32) #define SMB3_GCM256_CRYPTKEY_SIZE (32)
/* Maximum buffer size value we can send with 1 credit */ /* Maximum buffer size value we can send with 1 credit */
......
...@@ -754,8 +754,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) ...@@ -754,8 +754,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
} }
} }
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); cifs_dbg(FYI, "No file id matched, oplock break ignored\n");
return false; return true;
} }
void void
......
...@@ -2038,6 +2038,7 @@ smb2_duplicate_extents(const unsigned int xid, ...@@ -2038,6 +2038,7 @@ smb2_duplicate_extents(const unsigned int xid,
{ {
int rc; int rc;
unsigned int ret_data_len; unsigned int ret_data_len;
struct inode *inode;
struct duplicate_extents_to_file dup_ext_buf; struct duplicate_extents_to_file dup_ext_buf;
struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink); struct cifs_tcon *tcon = tlink_tcon(trgtfile->tlink);
...@@ -2054,10 +2055,21 @@ smb2_duplicate_extents(const unsigned int xid, ...@@ -2054,10 +2055,21 @@ smb2_duplicate_extents(const unsigned int xid,
cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n", cifs_dbg(FYI, "Duplicate extents: src off %lld dst off %lld len %lld\n",
src_off, dest_off, len); src_off, dest_off, len);
rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); inode = d_inode(trgtfile->dentry);
if (rc) if (inode->i_size < dest_off + len) {
goto duplicate_extents_out; rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false);
if (rc)
goto duplicate_extents_out;
/*
* Although also could set plausible allocation size (i_blocks)
* here in addition to setting the file size, in reflink
* it is likely that the target file is sparse. Its allocation
* size will be queried on next revalidate, but it is important
* to make sure that file's cached size is updated immediately
*/
cifs_setsize(inode, dest_off + len);
}
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid, rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
trgtfile->fid.volatile_fid, trgtfile->fid.volatile_fid,
FSCTL_DUPLICATE_EXTENTS_TO_FILE, FSCTL_DUPLICATE_EXTENTS_TO_FILE,
...@@ -4158,7 +4170,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) ...@@ -4158,7 +4170,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
if (ses->Suid == ses_id) { if (ses->Suid == ses_id) {
ses_enc_key = enc ? ses->smb3encryptionkey : ses_enc_key = enc ? ses->smb3encryptionkey :
ses->smb3decryptionkey; ses->smb3decryptionkey;
memcpy(key, ses_enc_key, SMB3_SIGN_KEY_SIZE); memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return 0; return 0;
} }
...@@ -4185,7 +4197,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, ...@@ -4185,7 +4197,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
int rc = 0; int rc = 0;
struct scatterlist *sg; struct scatterlist *sg;
u8 sign[SMB2_SIGNATURE_SIZE] = {}; u8 sign[SMB2_SIGNATURE_SIZE] = {};
u8 key[SMB3_SIGN_KEY_SIZE]; u8 key[SMB3_ENC_DEC_KEY_SIZE];
struct aead_request *req; struct aead_request *req;
char *iv; char *iv;
unsigned int iv_len; unsigned int iv_len;
...@@ -4209,10 +4221,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, ...@@ -4209,10 +4221,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
tfm = enc ? server->secmech.ccmaesencrypt : tfm = enc ? server->secmech.ccmaesencrypt :
server->secmech.ccmaesdecrypt; server->secmech.ccmaesdecrypt;
if (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM) if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
(server->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE); rc = crypto_aead_setkey(tfm, key, SMB3_GCM256_CRYPTKEY_SIZE);
else else
rc = crypto_aead_setkey(tfm, key, SMB3_SIGN_KEY_SIZE); rc = crypto_aead_setkey(tfm, key, SMB3_GCM128_CRYPTKEY_SIZE);
if (rc) { if (rc) {
cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc); cifs_server_dbg(VFS, "%s: Failed to set aead key %d\n", __func__, rc);
......
...@@ -298,7 +298,8 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, ...@@ -298,7 +298,8 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
{ {
unsigned char zero = 0x0; unsigned char zero = 0x0;
__u8 i[4] = {0, 0, 0, 1}; __u8 i[4] = {0, 0, 0, 1};
__u8 L[4] = {0, 0, 0, 128}; __u8 L128[4] = {0, 0, 0, 128};
__u8 L256[4] = {0, 0, 1, 0};
int rc = 0; int rc = 0;
unsigned char prfhash[SMB2_HMACSHA256_SIZE]; unsigned char prfhash[SMB2_HMACSHA256_SIZE];
unsigned char *hashptr = prfhash; unsigned char *hashptr = prfhash;
...@@ -354,8 +355,14 @@ static int generate_key(struct cifs_ses *ses, struct kvec label, ...@@ -354,8 +355,14 @@ static int generate_key(struct cifs_ses *ses, struct kvec label,
goto smb3signkey_ret; goto smb3signkey_ret;
} }
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash, if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
L, 4); (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
L256, 4);
} else {
rc = crypto_shash_update(&server->secmech.sdeschmacsha256->shash,
L128, 4);
}
if (rc) { if (rc) {
cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__); cifs_server_dbg(VFS, "%s: Could not update with L\n", __func__);
goto smb3signkey_ret; goto smb3signkey_ret;
...@@ -390,6 +397,9 @@ generate_smb3signingkey(struct cifs_ses *ses, ...@@ -390,6 +397,9 @@ generate_smb3signingkey(struct cifs_ses *ses,
const struct derivation_triplet *ptriplet) const struct derivation_triplet *ptriplet)
{ {
int rc; int rc;
#ifdef CONFIG_CIFS_DEBUG_DUMP_KEYS
struct TCP_Server_Info *server = ses->server;
#endif
/* /*
* All channels use the same encryption/decryption keys but * All channels use the same encryption/decryption keys but
...@@ -422,11 +432,11 @@ generate_smb3signingkey(struct cifs_ses *ses, ...@@ -422,11 +432,11 @@ generate_smb3signingkey(struct cifs_ses *ses,
rc = generate_key(ses, ptriplet->encryption.label, rc = generate_key(ses, ptriplet->encryption.label,
ptriplet->encryption.context, ptriplet->encryption.context,
ses->smb3encryptionkey, ses->smb3encryptionkey,
SMB3_SIGN_KEY_SIZE); SMB3_ENC_DEC_KEY_SIZE);
rc = generate_key(ses, ptriplet->decryption.label, rc = generate_key(ses, ptriplet->decryption.label,
ptriplet->decryption.context, ptriplet->decryption.context,
ses->smb3decryptionkey, ses->smb3decryptionkey,
SMB3_SIGN_KEY_SIZE); SMB3_ENC_DEC_KEY_SIZE);
if (rc) if (rc)
return rc; return rc;
} }
...@@ -442,14 +452,23 @@ generate_smb3signingkey(struct cifs_ses *ses, ...@@ -442,14 +452,23 @@ generate_smb3signingkey(struct cifs_ses *ses,
*/ */
cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid), cifs_dbg(VFS, "Session Id %*ph\n", (int)sizeof(ses->Suid),
&ses->Suid); &ses->Suid);
cifs_dbg(VFS, "Cipher type %d\n", server->cipher_type);
cifs_dbg(VFS, "Session Key %*ph\n", cifs_dbg(VFS, "Session Key %*ph\n",
SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response); SMB2_NTLMV2_SESSKEY_SIZE, ses->auth_key.response);
cifs_dbg(VFS, "Signing Key %*ph\n", cifs_dbg(VFS, "Signing Key %*ph\n",
SMB3_SIGN_KEY_SIZE, ses->smb3signingkey); SMB3_SIGN_KEY_SIZE, ses->smb3signingkey);
cifs_dbg(VFS, "ServerIn Key %*ph\n", if ((server->cipher_type == SMB2_ENCRYPTION_AES256_CCM) ||
SMB3_SIGN_KEY_SIZE, ses->smb3encryptionkey); (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) {
cifs_dbg(VFS, "ServerOut Key %*ph\n", cifs_dbg(VFS, "ServerIn Key %*ph\n",
SMB3_SIGN_KEY_SIZE, ses->smb3decryptionkey); SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3encryptionkey);
cifs_dbg(VFS, "ServerOut Key %*ph\n",
SMB3_GCM256_CRYPTKEY_SIZE, ses->smb3decryptionkey);
} else {
cifs_dbg(VFS, "ServerIn Key %*ph\n",
SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3encryptionkey);
cifs_dbg(VFS, "ServerOut Key %*ph\n",
SMB3_GCM128_CRYPTKEY_SIZE, ses->smb3decryptionkey);
}
#endif #endif
return rc; return rc;
} }
......
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