Skip to content

Commit

Permalink
CIFS: Fix use after free of file info structures
Browse files Browse the repository at this point in the history
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: 487317c ("cifs: add spinlock for the openFileList to cifsInodeInfo")
Fixes: cb24881 ("cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic")
Cc: Stable <[email protected]>
Reviewed-by: Ronnie Sahlberg <[email protected]>
Signed-off-by: Pavel Shilovsky <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
piastry authored and Steve French committed Oct 25, 2019
1 parent abe5707 commit 1a67c41
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,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;
}
Expand All @@ -421,9 +422,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);
atomic_dec(&tcon->num_local_opens);

Expand All @@ -440,6 +439,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 ?
Expand Down

0 comments on commit 1a67c41

Please sign in to comment.