]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: client: fix potential deadlock when releasing mids
authorPaulo Alcantara <pc@manguebit.com>
Wed, 25 Oct 2023 17:58:35 +0000 (14:58 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 2 May 2025 05:41:06 +0000 (07:41 +0200)
commit e6322fd177c6885a21dd4609dc5e5c973d1a2eb7 upstream.

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>
[cifs_mid_q_entry_release() is renamed to release_mid() and
 _cifs_mid_q_entry_release() is renamed to __release_mid() by
 commit 70f08f914a37 ("cifs: remove useless DeleteMidQEntry()")
 which is integrated into v6.0, so preserve old names in v5.10.]
Signed-off-by: Cliff Liu <donghua.liu@windriver.com>
Signed-off-by: He Zhe <Zhe.He@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/cifs/cifsproto.h
fs/cifs/smb2misc.c
fs/cifs/transport.c

index ca34cc1e1931a8bc3b40e3c1f6fc62365f6295ab..8c0ed2b602854f300cb59a20cd53030a46eb7a17 100644 (file)
@@ -85,7 +85,7 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer,
                                        struct TCP_Server_Info *server);
 extern void DeleteMidQEntry(struct mid_q_entry *midEntry);
 extern void cifs_delete_mid(struct mid_q_entry *mid);
-extern void cifs_mid_q_entry_release(struct mid_q_entry *midEntry);
+void _cifs_mid_q_entry_release(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);
@@ -646,4 +646,9 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
                return options;
 }
 
+static inline void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
+{
+       kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
+}
+
 #endif                 /* _CIFSPROTO_H */
index 660e00eb42060ac4798aa22d61bbf979c2b1cce4..64887856331ae5b8a98a1637091692d76a1ad9ef 100644 (file)
@@ -780,7 +780,7 @@ __smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid,
 {
        struct close_cancelled_open *cancelled;
 
-       cancelled = kzalloc(sizeof(*cancelled), GFP_ATOMIC);
+       cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
        if (!cancelled)
                return -ENOMEM;
 
index 4888939627081e9852a0f65bd7250c3430f8e42b..c6fd4223b3bea5a013312a6fbd6ddaa0d1c4fb4f 100644 (file)
@@ -88,7 +88,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
        return temp;
 }
 
-static void _cifs_mid_q_entry_release(struct kref *refcount)
+void _cifs_mid_q_entry_release(struct kref *refcount)
 {
        struct mid_q_entry *midEntry =
                        container_of(refcount, struct mid_q_entry, refcount);
@@ -168,13 +168,6 @@ static void _cifs_mid_q_entry_release(struct kref *refcount)
        mempool_free(midEntry, cifs_mid_poolp);
 }
 
-void cifs_mid_q_entry_release(struct mid_q_entry *midEntry)
-{
-       spin_lock(&GlobalMid_Lock);
-       kref_put(&midEntry->refcount, _cifs_mid_q_entry_release);
-       spin_unlock(&GlobalMid_Lock);
-}
-
 void DeleteMidQEntry(struct mid_q_entry *midEntry)
 {
        cifs_mid_q_entry_release(midEntry);