mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
CIFS: Fix use after free of file info structures
commit1a67c41596upstream. Currently the code assumes that if a file info entry belongs to lists of open file handles of an inode and a tcon then it has non-zero reference. The recent changes broke that assumption when putting the last reference of the file info. There may be a situation when a file is being deleted but nothing prevents another thread to reference it again and start using it. This happens because we do not hold the inode list lock while checking the number of references of the file info structure. Fix this by doing the proper locking when doing the check. Fixes:487317c994("cifs: add spinlock for the openFileList to cifsInodeInfo") Fixes:cb248819d2("cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic") Cc: Stable <stable@vger.kernel.org> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
71cf88165f
commit
01332b0370
@@ -403,10 +403,11 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
|
||||
bool oplock_break_cancelled;
|
||||
|
||||
spin_lock(&tcon->open_file_lock);
|
||||
|
||||
spin_lock(&cifsi->open_file_lock);
|
||||
spin_lock(&cifs_file->file_info_lock);
|
||||
if (--cifs_file->count > 0) {
|
||||
spin_unlock(&cifs_file->file_info_lock);
|
||||
spin_unlock(&cifsi->open_file_lock);
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
return;
|
||||
}
|
||||
@@ -419,9 +420,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
|
||||
cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
|
||||
|
||||
/* remove it from the lists */
|
||||
spin_lock(&cifsi->open_file_lock);
|
||||
list_del(&cifs_file->flist);
|
||||
spin_unlock(&cifsi->open_file_lock);
|
||||
list_del(&cifs_file->tlist);
|
||||
|
||||
if (list_empty(&cifsi->openFileList)) {
|
||||
@@ -437,6 +436,7 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
|
||||
cifs_set_oplock_level(cifsi, 0);
|
||||
}
|
||||
|
||||
spin_unlock(&cifsi->open_file_lock);
|
||||
spin_unlock(&tcon->open_file_lock);
|
||||
|
||||
oplock_break_cancelled = wait_oplock_handler ?
|
||||
|
||||
Reference in New Issue
Block a user