summaryrefslogtreecommitdiff
path: root/fs/smb/client/cifsproto.h
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-10-25 20:58:35 +0300
committerSteve French <stfrench@microsoft.com>2023-10-31 20:38:02 +0300
commite6322fd177c6885a21dd4609dc5e5c973d1a2eb7 (patch)
treeef37d8ba5db90d1c2eda090137ac422df0ad8d87 /fs/smb/client/cifsproto.h
parent72bc63f5e23a38b65ff2a201bdc11401d4223fa9 (diff)
downloadlinux-e6322fd177c6885a21dd4609dc5e5c973d1a2eb7.tar.xz
smb: client: fix potential deadlock when releasing mids
All release_mid() callers seem to hold a reference of @mid so there is no need to call kref_put(&mid->refcount, __release_mid) under @server->mid_lock spinlock. If they don't, then an use-after-free bug would have occurred anyways. By getting rid of such spinlock also fixes a potential deadlock as shown below CPU 0 CPU 1 ------------------------------------------------------------------ cifs_demultiplex_thread() cifs_debug_data_proc_show() release_mid() spin_lock(&server->mid_lock); spin_lock(&cifs_tcp_ses_lock) spin_lock(&server->mid_lock) __release_mid() smb2_find_smb_tcon() spin_lock(&cifs_tcp_ses_lock) *deadlock* Cc: stable@vger.kernel.org Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/client/cifsproto.h')
-rw-r--r--fs/smb/client/cifsproto.h7
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 0c37eefa18a5..890ceddae07e 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -81,7 +81,7 @@ extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx,
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
char *cifs_build_devname(char *nodename, const char *prepath);
extern void delete_mid(struct mid_q_entry *mid);
-extern void release_mid(struct mid_q_entry *mid);
+void __release_mid(struct kref *refcount);
extern void cifs_wake_up_task(struct mid_q_entry *mid);
extern int cifs_handle_standard(struct TCP_Server_Info *server,
struct mid_q_entry *mid);
@@ -740,4 +740,9 @@ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
return true;
}
+static inline void release_mid(struct mid_q_entry *mid)
+{
+ kref_put(&mid->refcount, __release_mid);
+}
+
#endif /* _CIFSPROTO_H */