]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
smb: client: let recv_done() avoid touching data_transfer after cleanup/move
authorStefan Metzmacher <metze@samba.org>
Mon, 4 Aug 2025 12:10:16 +0000 (14:10 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 6 Aug 2025 20:04:13 +0000 (15:04 -0500)
Calling enqueue_reassembly() and wake_up_interruptible(&info->wait_reassembly_queue)
or put_receive_buffer() means the response/data_transfer pointer might
get re-used by another thread, which means these should be
the last operations before calling return.

Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Fixes: f198186aa9bb ("CIFS: SMBD: Establish SMB Direct connection")
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/smbdirect.c

index d26b8cef82d65bd385bdc7c981094439b46f5bc4..47f2a6cc1c0cd6a9e3d35b3ecfbfa53cdb9c300f 100644 (file)
@@ -479,10 +479,6 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                data_transfer = smbd_response_payload(response);
                data_length = le32_to_cpu(data_transfer->data_length);
 
-               /*
-                * If this is a packet with data playload place the data in
-                * reassembly queue and wake up the reading thread
-                */
                if (data_length) {
                        if (info->full_packet_received)
                                response->first_segment = true;
@@ -491,16 +487,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                                info->full_packet_received = false;
                        else
                                info->full_packet_received = true;
-
-                       enqueue_reassembly(
-                               info,
-                               response,
-                               data_length);
-               } else
-                       put_receive_buffer(info, response);
-
-               if (data_length)
-                       wake_up_interruptible(&info->wait_reassembly_queue);
+               }
 
                atomic_dec(&info->receive_credits);
                info->receive_credit_target =
@@ -528,6 +515,16 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                        info->keep_alive_requested = KEEP_ALIVE_PENDING;
                }
 
+               /*
+                * If this is a packet with data playload place the data in
+                * reassembly queue and wake up the reading thread
+                */
+               if (data_length) {
+                       enqueue_reassembly(info, response, data_length);
+                       wake_up_interruptible(&info->wait_reassembly_queue);
+               } else
+                       put_receive_buffer(info, response);
+
                return;
        }