Skip to content

Commit 8bb14ca

Browse files
committed
Merge tag '5.13-rc3-smb3' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Seven smb3 fixes: one for stable, three others fix problems found in testing handle leases, and a compounded request fix" * tag '5.13-rc3-smb3' of git://git.samba.org/sfrench/cifs-2.6: Fix KASAN identified use-after-free issue. Defer close only when lease is enabled. Fix kernel oops when CONFIG_DEBUG_ATOMIC_SLEEP is enabled. cifs: Fix inconsistent indenting cifs: fix memory leak in smb2_copychunk_range SMB3: incorrect file id in requests compounded with open cifs: remove deadstore in cifs_close_all_deferred_files()
2 parents e8085a0 + 9687c85 commit 8bb14ca

7 files changed

Lines changed: 55 additions & 32 deletions

File tree

fs/cifs/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ struct workqueue_struct *cifsiod_wq;
133133
struct workqueue_struct *decrypt_wq;
134134
struct workqueue_struct *fileinfo_put_wq;
135135
struct workqueue_struct *cifsoplockd_wq;
136-
struct workqueue_struct *deferredclose_wq;
136+
struct workqueue_struct *deferredclose_wq;
137137
__u32 cifs_lock_secret;
138138

139139
/*

fs/cifs/cifsglob.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,7 @@ struct cifsFileInfo {
12571257
struct work_struct oplock_break; /* work for oplock breaks */
12581258
struct work_struct put; /* work for the final part of _put */
12591259
struct delayed_work deferred;
1260-
bool oplock_break_received; /* Flag to indicate oplock break */
1261-
bool deferred_scheduled;
1260+
bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
12621261
};
12631262

12641263
struct cifs_io_parms {
@@ -1418,6 +1417,7 @@ struct cifsInodeInfo {
14181417
struct inode vfs_inode;
14191418
struct list_head deferred_closes; /* list of deferred closes */
14201419
spinlock_t deferred_lock; /* protection on deferred list */
1420+
bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
14211421
};
14221422

14231423
static inline struct cifsInodeInfo *

fs/cifs/file.c

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
323323
cfile->dentry = dget(dentry);
324324
cfile->f_flags = file->f_flags;
325325
cfile->invalidHandle = false;
326-
cfile->oplock_break_received = false;
327-
cfile->deferred_scheduled = false;
326+
cfile->deferred_close_scheduled = false;
328327
cfile->tlink = cifs_get_tlink(tlink);
329328
INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
330329
INIT_WORK(&cfile->put, cifsFileInfo_put_work);
@@ -574,21 +573,18 @@ int cifs_open(struct inode *inode, struct file *file)
574573
file->f_op = &cifs_file_direct_ops;
575574
}
576575

577-
spin_lock(&CIFS_I(inode)->deferred_lock);
578576
/* Get the cached handle as SMB2 close is deferred */
579577
rc = cifs_get_readable_path(tcon, full_path, &cfile);
580578
if (rc == 0) {
581579
if (file->f_flags == cfile->f_flags) {
582580
file->private_data = cfile;
581+
spin_lock(&CIFS_I(inode)->deferred_lock);
583582
cifs_del_deferred_close(cfile);
584583
spin_unlock(&CIFS_I(inode)->deferred_lock);
585584
goto out;
586585
} else {
587-
spin_unlock(&CIFS_I(inode)->deferred_lock);
588586
_cifsFileInfo_put(cfile, true, false);
589587
}
590-
} else {
591-
spin_unlock(&CIFS_I(inode)->deferred_lock);
592588
}
593589

594590
if (server->oplocks)
@@ -878,12 +874,8 @@ void smb2_deferred_work_close(struct work_struct *work)
878874
struct cifsFileInfo, deferred.work);
879875

880876
spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
881-
if (!cfile->deferred_scheduled) {
882-
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
883-
return;
884-
}
885877
cifs_del_deferred_close(cfile);
886-
cfile->deferred_scheduled = false;
878+
cfile->deferred_close_scheduled = false;
887879
spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
888880
_cifsFileInfo_put(cfile, true, false);
889881
}
@@ -900,19 +892,26 @@ int cifs_close(struct inode *inode, struct file *file)
900892
file->private_data = NULL;
901893
dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
902894
if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
895+
cinode->lease_granted &&
903896
dclose) {
904897
if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags))
905898
inode->i_ctime = inode->i_mtime = current_time(inode);
906899
spin_lock(&cinode->deferred_lock);
907900
cifs_add_deferred_close(cfile, dclose);
908-
if (cfile->deferred_scheduled) {
909-
mod_delayed_work(deferredclose_wq,
910-
&cfile->deferred, cifs_sb->ctx->acregmax);
901+
if (cfile->deferred_close_scheduled &&
902+
delayed_work_pending(&cfile->deferred)) {
903+
/*
904+
* If there is no pending work, mod_delayed_work queues new work.
905+
* So, Increase the ref count to avoid use-after-free.
906+
*/
907+
if (!mod_delayed_work(deferredclose_wq,
908+
&cfile->deferred, cifs_sb->ctx->acregmax))
909+
cifsFileInfo_get(cfile);
911910
} else {
912911
/* Deferred close for files */
913912
queue_delayed_work(deferredclose_wq,
914913
&cfile->deferred, cifs_sb->ctx->acregmax);
915-
cfile->deferred_scheduled = true;
914+
cfile->deferred_close_scheduled = true;
916915
spin_unlock(&cinode->deferred_lock);
917916
return 0;
918917
}
@@ -2020,8 +2019,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
20202019
if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
20212020
continue;
20222021
if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
2023-
if ((!open_file->invalidHandle) &&
2024-
(!open_file->oplock_break_received)) {
2022+
if ((!open_file->invalidHandle)) {
20252023
/* found a good file */
20262024
/* lock it so it will not be closed on us */
20272025
cifsFileInfo_get(open_file);
@@ -4874,14 +4872,20 @@ void cifs_oplock_break(struct work_struct *work)
48744872
}
48754873
/*
48764874
* When oplock break is received and there are no active
4877-
* file handles but cached, then set the flag oplock_break_received.
4875+
* file handles but cached, then schedule deferred close immediately.
48784876
* So, new open will not use cached handle.
48794877
*/
48804878
spin_lock(&CIFS_I(inode)->deferred_lock);
48814879
is_deferred = cifs_is_deferred_close(cfile, &dclose);
4882-
if (is_deferred && cfile->deferred_scheduled) {
4883-
cfile->oplock_break_received = true;
4884-
mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
4880+
if (is_deferred &&
4881+
cfile->deferred_close_scheduled &&
4882+
delayed_work_pending(&cfile->deferred)) {
4883+
/*
4884+
* If there is no pending work, mod_delayed_work queues new work.
4885+
* So, Increase the ref count to avoid use-after-free.
4886+
*/
4887+
if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
4888+
cifsFileInfo_get(cfile);
48854889
}
48864890
spin_unlock(&CIFS_I(inode)->deferred_lock);
48874891
_cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);

fs/cifs/fs_context.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
11451145
/* if iocharset not set then load_nls_default
11461146
* is used by caller
11471147
*/
1148-
cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
1148+
cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
11491149
break;
11501150
case Opt_netbiosname:
11511151
memset(ctx->source_rfc1001_name, 0x20,

fs/cifs/misc.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,11 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
672672
spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
673673
}
674674

675+
/*
676+
* Critical section which runs after acquiring deferred_lock.
677+
* As there is no reference count on cifs_deferred_close, pdclose
678+
* should not be used outside deferred_lock.
679+
*/
675680
bool
676681
cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
677682
{
@@ -688,6 +693,9 @@ cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **
688693
return false;
689694
}
690695

696+
/*
697+
* Critical section which runs after acquiring deferred_lock.
698+
*/
691699
void
692700
cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
693701
{
@@ -707,6 +715,9 @@ cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *
707715
list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
708716
}
709717

718+
/*
719+
* Critical section which runs after acquiring deferred_lock.
720+
*/
710721
void
711722
cifs_del_deferred_close(struct cifsFileInfo *cfile)
712723
{
@@ -738,15 +749,19 @@ void
738749
cifs_close_all_deferred_files(struct cifs_tcon *tcon)
739750
{
740751
struct cifsFileInfo *cfile;
741-
struct cifsInodeInfo *cinode;
742752
struct list_head *tmp;
743753

744754
spin_lock(&tcon->open_file_lock);
745755
list_for_each(tmp, &tcon->openFileList) {
746756
cfile = list_entry(tmp, struct cifsFileInfo, tlist);
747-
cinode = CIFS_I(d_inode(cfile->dentry));
748-
if (delayed_work_pending(&cfile->deferred))
749-
mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
757+
if (delayed_work_pending(&cfile->deferred)) {
758+
/*
759+
* If there is no pending work, mod_delayed_work queues new work.
760+
* So, Increase the ref count to avoid use-after-free.
761+
*/
762+
if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
763+
cifsFileInfo_get(cfile);
764+
}
750765
}
751766
spin_unlock(&tcon->open_file_lock);
752767
}

fs/cifs/smb2ops.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,8 @@ smb2_copychunk_range(const unsigned int xid,
18611861
cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
18621862

18631863
/* Request server copy to target from src identified by key */
1864+
kfree(retbuf);
1865+
retbuf = NULL;
18641866
rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
18651867
trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
18661868
true /* is_fsctl */, (char *)pcchunk,
@@ -3981,6 +3983,7 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
39813983
unsigned int epoch, bool *purge_cache)
39823984
{
39833985
oplock &= 0xFF;
3986+
cinode->lease_granted = false;
39843987
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
39853988
return;
39863989
if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
@@ -4007,6 +4010,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
40074010
unsigned int new_oplock = 0;
40084011

40094012
oplock &= 0xFF;
4013+
cinode->lease_granted = true;
40104014
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
40114015
return;
40124016

fs/cifs/smb2pdu.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3900,10 +3900,10 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
39003900
* Related requests use info from previous read request
39013901
* in chain.
39023902
*/
3903-
shdr->SessionId = 0xFFFFFFFF;
3903+
shdr->SessionId = 0xFFFFFFFFFFFFFFFF;
39043904
shdr->TreeId = 0xFFFFFFFF;
3905-
req->PersistentFileId = 0xFFFFFFFF;
3906-
req->VolatileFileId = 0xFFFFFFFF;
3905+
req->PersistentFileId = 0xFFFFFFFFFFFFFFFF;
3906+
req->VolatileFileId = 0xFFFFFFFFFFFFFFFF;
39073907
}
39083908
}
39093909
if (remaining_bytes > io_parms->length)

0 commit comments

Comments
 (0)