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

Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/transport_rdma.c

index cd8a92fe372b13cb589940c312a69689304283dd..8d366db5f60547af18b035842bfd3c0aff59f8e4 100644 (file)
@@ -581,16 +581,11 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                        else
                                t->full_packet_received = true;
 
-                       enqueue_reassembly(t, recvmsg, (int)data_length);
-                       wake_up_interruptible(&t->wait_reassembly_queue);
-
                        spin_lock(&t->receive_credit_lock);
                        receive_credits = --(t->recv_credits);
                        avail_recvmsg_count = t->count_avail_recvmsg;
                        spin_unlock(&t->receive_credit_lock);
                } else {
-                       put_recvmsg(t, recvmsg);
-
                        spin_lock(&t->receive_credit_lock);
                        receive_credits = --(t->recv_credits);
                        avail_recvmsg_count = ++(t->count_avail_recvmsg);
@@ -612,6 +607,13 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
                if (is_receive_credit_post_required(receive_credits, avail_recvmsg_count))
                        mod_delayed_work(smb_direct_wq,
                                         &t->post_recv_credits_work, 0);
+
+               if (data_length) {
+                       enqueue_reassembly(t, recvmsg, (int)data_length);
+                       wake_up_interruptible(&t->wait_reassembly_queue);
+               } else
+                       put_recvmsg(t, recvmsg);
+
                return;
        }
        }