Commit 9351590f authored by Enzo Matsumiya's avatar Enzo Matsumiya Committed by Steve French

cifs: properly invalidate cached root handle when closing it

Cached root file was not being completely invalidated sometimes.

Reproducing:
- With a DFS share with 2 targets, one disabled and one enabled
- start some I/O on the mount
  # while true; do ls /mnt/dfs; done
- at the same time, disable the enabled target and enable the disabled
  one
- wait for DFS cache to expire
- on reconnect, the previous cached root handle should be invalid, but
  open_cached_dir_by_dentry() will still try to use it, but throws a
  use-after-free warning (kref_get())

Make smb2_close_cached_fid() invalidate all fields every time, but only
send an SMB2_close() when the entry is still valid.
Signed-off-by: default avatarEnzo Matsumiya <ematsumiya@suse.de>
Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8d014f5f
...@@ -689,13 +689,19 @@ smb2_close_cached_fid(struct kref *ref) ...@@ -689,13 +689,19 @@ smb2_close_cached_fid(struct kref *ref)
cifs_dbg(FYI, "clear cached root file handle\n"); cifs_dbg(FYI, "clear cached root file handle\n");
SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid, SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid,
cfid->fid->volatile_fid); cfid->fid->volatile_fid);
cfid->is_valid = false; }
cfid->file_all_info_is_valid = false;
cfid->has_lease = false; /*
if (cfid->dentry) { * We only check validity above to send SMB2_close,
dput(cfid->dentry); * but we still need to invalidate these entries
cfid->dentry = NULL; * when this function is called
} */
cfid->is_valid = false;
cfid->file_all_info_is_valid = false;
cfid->has_lease = false;
if (cfid->dentry) {
dput(cfid->dentry);
cfid->dentry = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment