Commit 4871b7cb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'v6.16-rc6-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - fix creating special files to Samba when using SMB3.1.1 POSIX
   Extensions

 - fix incorrect caching on new file creation with directory leases
   enabled

 - two use after free fixes: one in oplock_break and one in async
   decryption

* tag 'v6.16-rc6-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  Fix SMB311 posix special file creation to servers which do not advertise reparse support
  smb: invalidate and close cached directory when creating child entries
  smb: client: fix use-after-free in crypt_message when using async crypto
  smb: client: fix use-after-free in cifs_oplock_break
parents 27c25703 8767cb3f
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -190,6 +190,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
	int disposition;
	struct TCP_Server_Info *server = tcon->ses->server;
	struct cifs_open_parms oparms;
	struct cached_fid *parent_cfid = NULL;
	int rdwr_for_fscache = 0;
	__le32 lease_flags = 0;

@@ -313,10 +314,10 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
	if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
		create_options |= CREATE_OPTION_READONLY;


retry_open:
	if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
		struct cached_fid *parent_cfid;

		parent_cfid = NULL;
		spin_lock(&tcon->cfids->cfid_list_lock);
		list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
			if (parent_cfid->dentry == direntry->d_parent) {
@@ -327,6 +328,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
					memcpy(fid->parent_lease_key,
					       parent_cfid->fid.lease_key,
					       SMB2_LEASE_KEY_SIZE);
					parent_cfid->dirents.is_valid = false;
				}
				break;
			}
+9 −1
Original line number Diff line number Diff line
@@ -3088,7 +3088,8 @@ void cifs_oplock_break(struct work_struct *work)
	struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
						  oplock_break);
	struct inode *inode = d_inode(cfile->dentry);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct super_block *sb = inode->i_sb;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	struct cifsInodeInfo *cinode = CIFS_I(inode);
	struct cifs_tcon *tcon;
	struct TCP_Server_Info *server;
@@ -3098,6 +3099,12 @@ void cifs_oplock_break(struct work_struct *work)
	__u64 persistent_fid, volatile_fid;
	__u16 net_fid;

	/*
	 * Hold a reference to the superblock to prevent it and its inodes from
	 * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
	 * may release the last reference to the sb and trigger inode eviction.
	 */
	cifs_sb_active(sb);
	wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
			TASK_UNINTERRUPTIBLE);

@@ -3170,6 +3177,7 @@ void cifs_oplock_break(struct work_struct *work)
	cifs_put_tlink(tlink);
out:
	cifs_done_oplock_break(cinode);
	cifs_sb_deactive(sb);
}

static int cifs_swap_activate(struct swap_info_struct *sis,
+2 −1
Original line number Diff line number Diff line
@@ -1346,6 +1346,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
	 * empty object on the server.
	 */
	if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
		if (!tcon->posix_extensions)
			return ERR_PTR(-EOPNOTSUPP);

	oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
+8 −2
Original line number Diff line number Diff line
@@ -4316,6 +4316,7 @@ 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);
	unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
	void *creq;
	size_t sensitive_size;
@@ -4366,7 +4367,11 @@ 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);

	rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
	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);

	if (!rc && enc)
		memcpy(&tr_hdr->Signature, sign, SMB2_SIGNATURE_SIZE);
@@ -5255,7 +5260,8 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
		rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
					full_path, mode, dev);
	} else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
	} else if ((le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)
		|| (tcon->posix_extensions)) {
		rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
					full_path, mode, dev);
	}