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, 27 Apr 2023 16:00:10 +0000 (11:00 -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 7f085ed2d866bb751270176120e0fc26d5d60d11..f76e9bb7d74231682439628efde5c806c4ac895f 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)