Skip to content

Commit 4871b7c

Browse files
committed
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
2 parents 27c2570 + 8767cb3 commit 4871b7c

File tree

4 files changed

+23
-6
lines changed

4 files changed

+23
-6
lines changed

fs/smb/client/dir.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
190190
int disposition;
191191
struct TCP_Server_Info *server = tcon->ses->server;
192192
struct cifs_open_parms oparms;
193+
struct cached_fid *parent_cfid = NULL;
193194
int rdwr_for_fscache = 0;
194195
__le32 lease_flags = 0;
195196

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

317+
316318
retry_open:
317319
if (tcon->cfids && direntry->d_parent && server->dialect >= SMB30_PROT_ID) {
318-
struct cached_fid *parent_cfid;
319-
320+
parent_cfid = NULL;
320321
spin_lock(&tcon->cfids->cfid_list_lock);
321322
list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
322323
if (parent_cfid->dentry == direntry->d_parent) {
@@ -327,6 +328,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
327328
memcpy(fid->parent_lease_key,
328329
parent_cfid->fid.lease_key,
329330
SMB2_LEASE_KEY_SIZE);
331+
parent_cfid->dirents.is_valid = false;
330332
}
331333
break;
332334
}

fs/smb/client/file.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3088,7 +3088,8 @@ void cifs_oplock_break(struct work_struct *work)
30883088
struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
30893089
oplock_break);
30903090
struct inode *inode = d_inode(cfile->dentry);
3091-
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
3091+
struct super_block *sb = inode->i_sb;
3092+
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
30923093
struct cifsInodeInfo *cinode = CIFS_I(inode);
30933094
struct cifs_tcon *tcon;
30943095
struct TCP_Server_Info *server;
@@ -3098,6 +3099,12 @@ void cifs_oplock_break(struct work_struct *work)
30983099
__u64 persistent_fid, volatile_fid;
30993100
__u16 net_fid;
31003101

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

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

31753183
static int cifs_swap_activate(struct swap_info_struct *sis,

fs/smb/client/smb2inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,8 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
13461346
* empty object on the server.
13471347
*/
13481348
if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
1349-
return ERR_PTR(-EOPNOTSUPP);
1349+
if (!tcon->posix_extensions)
1350+
return ERR_PTR(-EOPNOTSUPP);
13501351

13511352
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
13521353
SYNCHRONIZE | DELETE |

fs/smb/client/smb2ops.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4316,6 +4316,7 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43164316
u8 key[SMB3_ENC_DEC_KEY_SIZE];
43174317
struct aead_request *req;
43184318
u8 *iv;
4319+
DECLARE_CRYPTO_WAIT(wait);
43194320
unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
43204321
void *creq;
43214322
size_t sensitive_size;
@@ -4366,7 +4367,11 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
43664367
aead_request_set_crypt(req, sg, sg, crypt_len, iv);
43674368
aead_request_set_ad(req, assoc_data_len);
43684369

4369-
rc = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
4370+
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
4371+
crypto_req_done, &wait);
4372+
4373+
rc = crypto_wait_req(enc ? crypto_aead_encrypt(req)
4374+
: crypto_aead_decrypt(req), &wait);
43704375

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

0 commit comments

Comments
 (0)