From 7fbda6d916d5ff5aa7c51fdf6280e1f53ee764a1 Mon Sep 17 00:00:00 2001 From: Alexey Marchuk Date: Fri, 22 Jul 2022 19:01:53 +0300 Subject: [PATCH] nvmf/rdma: Fix data_wr_pool corruption When there are not enought transport buffers for multi SGL request in state NEED_BUFFER, WRs received from the data_wr_pool are returned back to the pool. However rdma_req->data.wr.next pointer still points to the first WR from the pool. Usually it doesn't cause any problems since rdma_req will try to fill buffers again, but when qpair is being destroyed, all requests are completed forcefully. When the request is completed and data.wr.next pointer is not NULL, we'll try to put already released WRs into the pool one more time. That corrupts the pool and leads to undefined behavior. Fixes #2541 Signed-off-by: Alexey Marchuk Change-Id: I238b92eec132d8d845330362af6f335421177454 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13760 Reviewed-by: Michael Haeuptle Reviewed-by: Changpeng Liu Reviewed-by: Ben Walker Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins --- lib/nvmf/rdma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/nvmf/rdma.c b/lib/nvmf/rdma.c index 0458ffa99..4476465f4 100644 --- a/lib/nvmf/rdma.c +++ b/lib/nvmf/rdma.c @@ -613,11 +613,14 @@ nvmf_rdma_request_free_data(struct spdk_nvmf_rdma_request *rdma_req, data_wr->wr.num_sge = 0; next_send_wr = data_wr->wr.next; if (data_wr != &rdma_req->data) { + data_wr->wr.next = NULL; spdk_mempool_put(rtransport->data_wr_pool, data_wr); } data_wr = (!next_send_wr || next_send_wr == &rdma_req->rsp.wr) ? NULL : SPDK_CONTAINEROF(next_send_wr, struct spdk_nvmf_rdma_request_data, wr); } + rdma_req->data.wr.next = NULL; + rdma_req->rsp.wr.next = NULL; } static void @@ -1914,8 +1917,6 @@ _nvmf_rdma_request_free(struct spdk_nvmf_rdma_request *rdma_req, rdma_req->req.length = 0; rdma_req->req.iovcnt = 0; rdma_req->req.data = NULL; - rdma_req->rsp.wr.next = NULL; - rdma_req->data.wr.next = NULL; rdma_req->offset = 0; rdma_req->req.dif_enabled = false; rdma_req->fused_failed = false;