summaryrefslogtreecommitdiff
path: root/fs/cifs/readdir.c
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@axis.com>2015-12-23 07:32:41 +0100
committerSteve French <sfrench@localhost.localdomain>2016-01-14 14:35:58 -0600
commit820962dc700598ffe8cd21b967e30e7520c34748 (patch)
tree21cfcb56a523a372e1518d7fce1ed9e7cccb0df5 /fs/cifs/readdir.c
parent373512ec5c105ed09e3738196dcb257dfab65cba (diff)
cifs: fix race between call_async() and reconnect()
cifs_call_async() queues the MID to the pending list and calls smb_send_rqst(). If smb_send_rqst() performs a partial send, it sets the tcpStatus to CifsNeedReconnect and returns an error code to cifs_call_async(). In this case, cifs_call_async() removes the MID from the list and returns to the caller. However, cifs_call_async() releases the server mutex _before_ removing the MID. This means that a cifs_reconnect() can race with this function and manage to remove the MID from the list and delete the entry before cifs_call_async() calls cifs_delete_mid(). This leads to various crashes due to the use after free in cifs_delete_mid(). Task1 Task2 cifs_call_async(): - rc = -EAGAIN - mutex_unlock(srv_mutex) cifs_reconnect(): - mutex_lock(srv_mutex) - mutex_unlock(srv_mutex) - list_delete(mid) - mid->callback() cifs_writev_callback(): - mutex_lock(srv_mutex) - delete(mid) - mutex_unlock(srv_mutex) - cifs_delete_mid(mid) <---- use after free Fix this by removing the MID in cifs_call_async() before releasing the srv_mutex. Also hold the srv_mutex in cifs_reconnect() until the MIDs are moved out of the pending list. Signed-off-by: Rabin Vincent <rabin.vincent@axis.com> Acked-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> CC: Stable <stable@vger.kernel.org> Signed-off-by: Steve French <sfrench@localhost.localdomain>
Diffstat (limited to 'fs/cifs/readdir.c')
0 files changed, 0 insertions, 0 deletions