SMB3: Add missing locks to protect deferred close file list
authorBharath SM <bharathsm@microsoft.com>
Thu, 20 Apr 2023 13:54:33 +0000 (13:54 +0000)
committerSteve French <stfrench@microsoft.com>
Thu, 1 Jun 2023 04:45:56 +0000 (23:45 -0500)
cifs_del_deferred_close function has a critical section which modifies
the deferred close file list. We must acquire deferred_lock before
calling cifs_del_deferred_close function.

Fixes: ca08d0eac020 ("cifs: Fix memory leak on the deferred close")
Signed-off-by: Bharath SM <bharathsm@microsoft.com>
Acked-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Acked-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/misc.c

index 2f3f27b772232a6062f705dd68cd29d44315a3f1..bbedeefcb235ba51ecb90c2912cffdc15492fb15 100644 (file)
@@ -749,7 +749,9 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
        list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
                if (delayed_work_pending(&cfile->deferred)) {
                        if (cancel_delayed_work(&cfile->deferred)) {
+                               spin_lock(&cifs_inode->deferred_lock);
                                cifs_del_deferred_close(cfile);
+                               spin_unlock(&cifs_inode->deferred_lock);
 
                                tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
                                if (tmp_list == NULL)
@@ -780,7 +782,9 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
        list_for_each_entry(cfile, &tcon->openFileList, tlist) {
                if (delayed_work_pending(&cfile->deferred)) {
                        if (cancel_delayed_work(&cfile->deferred)) {
+                               spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
                                cifs_del_deferred_close(cfile);
+                               spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
 
                                tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
                                if (tmp_list == NULL)
@@ -815,7 +819,9 @@ cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, const char *path)
                if (strstr(full_path, path)) {
                        if (delayed_work_pending(&cfile->deferred)) {
                                if (cancel_delayed_work(&cfile->deferred)) {
+                                       spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
                                        cifs_del_deferred_close(cfile);
+                                       spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
 
                                        tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
                                        if (tmp_list == NULL)