diff options
Diffstat (limited to 'fs/smb/client/smb2ops.c')
-rw-r--r-- | fs/smb/client/smb2ops.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 7381ec333c6d..24a2aa04a108 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -1158,7 +1158,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid fid; unsigned int size[1]; void *data[1]; - struct smb2_file_full_ea_info *ea = NULL; + struct smb2_file_full_ea_info *ea; struct smb2_query_info_rsp *rsp; int rc, used_len = 0; int retries = 0, cur_sleep = 1; @@ -1179,6 +1179,7 @@ replay_again: if (!utf16_path) return -ENOMEM; + ea = NULL; resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER; vars = kzalloc(sizeof(*vars), GFP_KERNEL); if (!vars) { @@ -2177,7 +2178,7 @@ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon, NULL, 0 /* no input data */, max_response_size, (char **)&retbuf, &ret_data_len); - cifs_dbg(FYI, "enum snaphots ioctl returned %d and ret buflen is %d\n", + cifs_dbg(FYI, "enum snapshots ioctl returned %d and ret buflen is %d\n", rc, ret_data_len); if (rc) return rc; @@ -2838,7 +2839,7 @@ out_free_path: static int smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, struct kstatfs *buf) + const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf) { struct smb2_query_info_rsp *rsp; struct smb2_fs_full_size_info *info = NULL; @@ -2847,7 +2848,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon, int rc; - rc = smb2_query_info_compound(xid, tcon, "", + rc = smb2_query_info_compound(xid, tcon, path, FILE_READ_ATTRIBUTES, FS_FULL_SIZE_INFORMATION, SMB2_O_INFO_FILESYSTEM, @@ -2875,28 +2876,33 @@ qfs_exit: static int smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon, - struct cifs_sb_info *cifs_sb, struct kstatfs *buf) + const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf) { int rc; - __le16 srch_path = 0; /* Null - open root of share */ + __le16 *utf16_path = NULL; u8 oplock = SMB2_OPLOCK_LEVEL_NONE; struct cifs_open_parms oparms; struct cifs_fid fid; if (!tcon->posix_extensions) - return smb2_queryfs(xid, tcon, cifs_sb, buf); + return smb2_queryfs(xid, tcon, path, cifs_sb, buf); oparms = (struct cifs_open_parms) { .tcon = tcon, - .path = "", + .path = path, .desired_access = FILE_READ_ATTRIBUTES, .disposition = FILE_OPEN, .create_options = cifs_create_options(cifs_sb, 0), .fid = &fid, }; - rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, + utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); + if (utf16_path == NULL) + return -ENOMEM; + + rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL, NULL); + kfree(utf16_path); if (rc) return rc; @@ -3583,7 +3589,7 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, /* * At this point, we are trying to fallocate an internal * regions of a sparse file. Since smb2 does not have a - * fallocate command we have two otions on how to emulate this. + * fallocate command we have two options on how to emulate this. * We can either turn the entire file to become non-sparse * which we only do if the fallocate is for virtually * the whole file, or we can overwrite the region with zeroes @@ -4309,7 +4315,7 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key) */ static int crypt_message(struct TCP_Server_Info *server, int num_rqst, - struct smb_rqst *rqst, int enc) + struct smb_rqst *rqst, int enc, struct crypto_aead *tfm) { struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)rqst[0].rq_iov[0].iov_base; @@ -4320,8 +4326,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, u8 key[SMB3_ENC_DEC_KEY_SIZE]; struct aead_request *req; u8 *iv; - DECLARE_CRYPTO_WAIT(wait); - struct crypto_aead *tfm; unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize); void *creq; size_t sensitive_size; @@ -4333,14 +4337,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, return rc; } - rc = smb3_crypto_aead_allocate(server); - if (rc) { - cifs_server_dbg(VFS, "%s: crypto alloc failed\n", __func__); - return rc; - } - - tfm = enc ? server->secmech.enc : server->secmech.dec; - 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); @@ -4380,11 +4376,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst, aead_request_set_crypt(req, sg, sg, crypt_len, iv); aead_request_set_ad(req, assoc_data_len); - aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - crypto_req_done, &wait); - - rc = crypto_wait_req(enc ? crypto_aead_encrypt(req) - : crypto_aead_decrypt(req), &wait); + rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); if (!rc && enc) memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE); @@ -4526,7 +4518,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst, /* fill the 1st iov with a transform header */ fill_transform_hdr(tr_hdr, orig_len, old_rq, server->cipher_type); - rc = crypt_message(server, num_rqst, new_rq, 1); + rc = crypt_message(server, num_rqst, new_rq, 1, server->secmech.enc); cifs_dbg(FYI, "Encrypt message returned %d\n", rc); if (rc) goto err_free; @@ -4551,8 +4543,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, unsigned int buf_data_size, struct iov_iter *iter, bool is_offloaded) { - struct kvec iov[2]; + struct crypto_aead *tfm; struct smb_rqst rqst = {NULL}; + struct kvec iov[2]; size_t iter_size = 0; int rc; @@ -4568,9 +4561,31 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf, iter_size = iov_iter_count(iter); } - rc = crypt_message(server, 1, &rqst, 0); + if (is_offloaded) { + if ((server->cipher_type == SMB2_ENCRYPTION_AES128_GCM) || + (server->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) + tfm = crypto_alloc_aead("gcm(aes)", 0, 0); + else + tfm = crypto_alloc_aead("ccm(aes)", 0, 0); + if (IS_ERR(tfm)) { + rc = PTR_ERR(tfm); + cifs_server_dbg(VFS, "%s: Failed alloc decrypt TFM, rc=%d\n", __func__, rc); + + return rc; + } + } else { + if (unlikely(!server->secmech.dec)) + return -EIO; + + tfm = server->secmech.dec; + } + + rc = crypt_message(server, 1, &rqst, 0, tfm); cifs_dbg(FYI, "Decrypt message returned %d\n", rc); + if (is_offloaded) + crypto_free_aead(tfm); + if (rc) return rc; @@ -4869,9 +4884,12 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid, goto discard_data; server->total_read += rc; - if (rc < len) - iov_iter_zero(len - rc, &iter); - iov_iter_revert(&iter, len); + if (rc < len) { + struct iov_iter tmp = iter; + + iov_iter_advance(&tmp, rc); + iov_iter_zero(len - rc, &tmp); + } iov_iter_truncate(&iter, dw->len); rc = cifs_discard_remaining_data(server); |