linux/fs/cifs
Aurelien Aptel e79b0332ae cifs: ignore cached share root handle closing errors
Fix tcon use-after-free and NULL ptr deref.

Customer system crashes with the following kernel log:

[462233.169868] CIFS VFS: Cancelling wait for mid 4894753 cmd: 14       => a QUERY DIR
[462233.228045] CIFS VFS: cifs_put_smb_ses: Session Logoff failure rc=-4
[462233.305922] CIFS VFS: cifs_put_smb_ses: Session Logoff failure rc=-4
[462233.306205] CIFS VFS: cifs_put_smb_ses: Session Logoff failure rc=-4
[462233.347060] CIFS VFS: cifs_put_smb_ses: Session Logoff failure rc=-4
[462233.347107] CIFS VFS: Close unmatched open
[462233.347113] BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
...
    [exception RIP: cifs_put_tcon+0xa0] (this is doing tcon->ses->server)
 #6 [...] smb2_cancelled_close_fid at ... [cifs]
 #7 [...] process_one_work at ...
 #8 [...] worker_thread at ...
 #9 [...] kthread at ...

The most likely explanation we have is:

* When we put the last reference of a tcon (refcount=0), we close the
  cached share root handle.
* If closing a handle is interrupted, SMB2_close() will
  queue a SMB2_close() in a work thread.
* The queued object keeps a tcon ref so we bump the tcon
  refcount, jumping from 0 to 1.
* We reach the end of cifs_put_tcon(), we free the tcon object despite
  it now having a refcount of 1.
* The queued work now runs, but the tcon, ses & server was freed in
  the meantime resulting in a crash.

THREAD 1
========
cifs_put_tcon                 => tcon refcount reach 0
  SMB2_tdis
   close_shroot_lease
    close_shroot_lease_locked => if cached root has lease && refcount = 0
     smb2_close_cached_fid    => if cached root valid
      SMB2_close              => retry close in a thread if interrupted
       smb2_handle_cancelled_close
        __smb2_handle_cancelled_close    => !! tcon refcount bump 0 => 1 !!
         INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
         queue_work(cifsiod_wq, &cancelled->work) => queue work
 tconInfoFree(tcon);    ==> freed!
 cifs_put_smb_ses(ses); ==> freed!

THREAD 2 (workqueue)
========
smb2_cancelled_close_fid
  SMB2_close(0, cancelled->tcon, ...); => use-after-free of tcon
  cifs_put_tcon(cancelled->tcon);      => tcon refcount reach 0 second time
  *CRASH*

Fixes: d919131935 ("CIFS: Close cached root handle only if it has a lease")
Signed-off-by: Aurelien Aptel <aaptel@suse.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
2020-04-07 12:40:40 -05:00
..
Kconfig various cifs/smb3 fixes (including for share deleted cases) and features including improved encrypted read performance, and various debugging improvements 2019-09-19 10:32:16 -07:00
Makefile cifs: Add support for root file systems 2019-09-16 11:43:38 -05:00
asn1.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
cache.c cifs: use 64-bit timestamps for fscache 2018-08-07 14:15:41 -05:00
cifs_debug.c proc: convert everything to "struct proc_ops" 2020-02-04 03:05:26 +00:00
cifs_debug.h cifs: add a debug macro that prints \\server\share for errors 2019-09-16 11:43:38 -05:00
cifs_dfs_ref.c cifs: fix potential mismatch of UNC paths 2020-02-24 14:20:38 -06:00
cifs_fs_sb.h smb3: add mount option to allow RW caching of share accessed by only 1 client 2019-09-16 11:43:38 -05:00
cifs_ioctl.h cifs: add SMB3 change notification support 2020-02-06 09:14:28 -06:00
cifs_spnego.c cifs: switch servers depending on binding state 2019-11-25 01:16:30 -06:00
cifs_spnego.h [CIFS] Rename three structures to avoid camel case 2011-05-27 04:34:02 +00:00
cifs_unicode.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
cifs_unicode.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
cifs_uniupr.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
cifsacl.c fs/cifs: fix gcc warning in sid_to_id 2020-03-22 22:49:09 -05:00
cifsacl.h smb3: fix mode passed in on create for modetosid mount option 2019-12-06 14:15:52 -06:00
cifsencrypt.c fs: cifs: switch to RC4 library interface 2019-06-20 14:19:55 +08:00
cifsfs.c cifs: do d_move in rename 2020-03-22 22:49:09 -05:00
cifsfs.h cifs: update internal module version number 2020-03-29 16:59:31 -05:00
cifsglob.h cifs: fix rename() by ensuring source handle opened with DELETE bit 2020-02-24 14:20:38 -06:00
cifspdu.h cifs: cifspdu.h: Replace zero-length array with flexible-array member 2020-03-22 22:49:10 -05:00
cifsproto.h cifs: handle prefix paths in reconnect 2020-03-22 22:49:09 -05:00
cifsroot.c cifs: cifsroot: add more err checking 2019-09-16 11:43:39 -05:00
cifssmb.c cifs: make use of cap_unix(ses) in cifs_reconnect_tcon() 2020-03-22 22:49:09 -05:00
connect.c cifs: clear PF_MEMALLOC before exiting demultiplex thread 2020-03-22 22:49:10 -05:00
dfs_cache.c cifs: handle prefix paths in reconnect 2020-03-22 22:49:09 -05:00
dfs_cache.h cifs: handle prefix paths in reconnect 2020-03-22 22:49:09 -05:00
dir.c cifs_atomic_open(): fix double-put on late allocation failure 2020-03-12 18:25:20 -04:00
dns_resolve.c keys: Pass the network namespace into request_key mechanism 2019-06-27 23:02:12 +01:00
dns_resolve.h DNS: Separate out CIFS DNS Resolver code 2010-08-05 17:17:51 +00:00
export.c docs: fs: convert docs without extension to ReST 2019-07-31 13:31:05 -06:00
file.c CIFS: Fix bug which the return value by asynchronous read is error 2020-03-22 22:49:10 -05:00
fscache.c cifs: use 64-bit timestamps for fscache 2018-08-07 14:15:41 -05:00
fscache.h cifs: use 64-bit timestamps for fscache 2018-08-07 14:15:41 -05:00
inode.c cifs: do d_move in rename 2020-03-22 22:49:09 -05:00
ioctl.c cifs: add SMB3 change notification support 2020-02-06 09:14:28 -06:00
link.c cifs: add SMB2_open() arg to return POSIX data 2020-03-22 22:49:09 -05:00
misc.c cifs: handle prefix paths in reconnect 2020-03-22 22:49:09 -05:00
netmisc.c fs: cifs: mute -Wunused-const-variable message 2019-10-06 22:04:35 -05:00
nterr.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 61 2019-05-24 17:36:45 +02:00
nterr.h treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 61 2019-05-24 17:36:45 +02:00
ntlmssp.h cifs: dynamic allocation of ntlmssp blob 2016-06-23 23:45:07 -05:00
readdir.c cifs: plumb smb2 POSIX dir enumeration 2020-03-22 22:49:09 -05:00
rfc1002pdu.h
sess.c cifs: make multichannel warning more visible 2020-02-06 09:12:16 -06:00
smb1ops.c cifs: fix rename() by ensuring source handle opened with DELETE bit 2020-02-24 14:20:38 -06:00
smb2file.c cifs: allow unlock flock and OFD lock across fork 2020-03-22 22:49:09 -05:00
smb2glob.h cifs: change SMB2_OP_RENAME and SMB2_OP_HARDLINK to use compounding 2018-10-23 21:16:04 -05:00
smb2inode.c cifs: fix rename() by ensuring source handle opened with DELETE bit 2020-02-24 14:20:38 -06:00
smb2maperror.c smb3: improve handling of share deleted (and share recreated) 2019-09-16 11:43:38 -05:00
smb2misc.c cifs: ignore cached share root handle closing errors 2020-04-07 12:40:40 -05:00
smb2ops.c cifs: smbd: Calculate the correct maximum packet size for segmented SMBDirect send/receive 2020-03-29 16:41:49 -05:00
smb2pdu.c cifs: add SMB2_open() arg to return POSIX data 2020-03-22 22:49:09 -05:00
smb2pdu.h cifs: smbd: Calculate the correct maximum packet size for segmented SMBDirect send/receive 2020-03-29 16:41:49 -05:00
smb2proto.h cifs: add SMB2_open() arg to return POSIX data 2020-03-22 22:49:09 -05:00
smb2status.h cifs: don't use __constant_cpu_to_le32() 2019-05-07 23:24:54 -05:00
smb2transport.c cifs: update internal module version number 2020-03-29 16:59:31 -05:00
smbdirect.c cifs: smbd: Check and extend sender credits in interrupt context 2020-03-29 16:42:36 -05:00
smbdirect.h cifs: smbd: Check and extend sender credits in interrupt context 2020-03-29 16:42:36 -05:00
smbencrypt.c fs: cifs: move from the crypto cipher API to the new DES library interface 2019-08-22 14:57:34 +10:00
smberr.h cifs: map NT_STATUS_ERROR_WRITE_PROTECTED to -EROFS 2010-08-02 12:40:40 +00:00
smbfsctl.h smb3: Add missing reparse tags 2019-09-24 23:31:32 -05:00
trace.c smb3: Cleanup license mess 2019-01-24 09:37:33 -06:00
trace.h cifs: Add tracepoints for errors on flush or fsync 2020-02-05 18:24:19 -06:00
transport.c cifs: Allocate encryption header through kmalloc 2020-03-29 16:42:54 -05:00
winucase.c treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156 2019-05-30 11:26:35 -07:00
xattr.c CIFS: Add support for setting owner info, dos attributes, and create time 2020-01-26 19:24:17 -06:00