Hannes Reinecke 0e83d5
From: Varun Prakash <varun@chelsio.com>
Hannes Reinecke 0e83d5
Date: Tue, 26 Oct 2021 19:01:55 +0530
Hannes Reinecke 0e83d5
Subject: [PATCH] nvme-tcp: fix possible req->offset corruption
Hannes Reinecke 0e83d5
Git-commit: ce7723e9cdae4eb3030da082876580f4b2dc0861
Hannes Reinecke 0e83d5
Patch-mainline: v5.15-rc1
Hannes Reinecke 0e83d5
References: git-fixes
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
With commit db5ad6b7f8cd ("nvme-tcp: try to send request in queue_rq
Hannes Reinecke 0e83d5
context") r2t and response PDU can get processed while send function
Hannes Reinecke 0e83d5
is executing.
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
Current data digest send code uses req->offset after kernel_sendmsg(),
Hannes Reinecke 0e83d5
this creates a race condition where req->offset gets reset before it
Hannes Reinecke 0e83d5
is used in send function.
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
This can happen in two cases -
Hannes Reinecke 0e83d5
1. Target sends r2t PDU which resets req->offset.
Hannes Reinecke 0e83d5
2. Target send response PDU which completes the req and then req is
Hannes Reinecke 0e83d5
   used for a new command, nvme_tcp_setup_cmd_pdu() resets req->offset.
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
Fix this by storing req->offset in a local variable and using
Hannes Reinecke 0e83d5
this local variable after kernel_sendmsg().
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
Fixes: db5ad6b7f8cd ("nvme-tcp: try to send request in queue_rq context")
Hannes Reinecke 0e83d5
Signed-off-by: Varun Prakash <varun@chelsio.com>
Hannes Reinecke 0e83d5
Reviewed-by: Keith Busch <kbusch@kernel.org>
Hannes Reinecke 0e83d5
Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
Hannes Reinecke 0e83d5
Signed-off-by: Christoph Hellwig <hch@lst.de>
Hannes Reinecke 0e83d5
Acked-by: Hannes Reinecke <hare@suse.com>
Hannes Reinecke 0e83d5
---
Hannes Reinecke 0e83d5
 drivers/nvme/host/tcp.c | 3 ++-
Hannes Reinecke 0e83d5
 1 file changed, 2 insertions(+), 1 deletion(-)
Hannes Reinecke 0e83d5
Hannes Reinecke 0e83d5
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
Hannes Reinecke 0e83d5
index 0626d14e6d4c..1a209f0d7181 100644
Hannes Reinecke 0e83d5
--- a/drivers/nvme/host/tcp.c
Hannes Reinecke 0e83d5
+++ b/drivers/nvme/host/tcp.c
Hannes Reinecke 0e83d5
@@ -1050,6 +1050,7 @@ static int nvme_tcp_try_send_data_pdu(struct nvme_tcp_request *req)
Hannes Reinecke 0e83d5
 static int nvme_tcp_try_send_ddgst(struct nvme_tcp_request *req)
Hannes Reinecke 0e83d5
 {
Hannes Reinecke 0e83d5
 	struct nvme_tcp_queue *queue = req->queue;
Hannes Reinecke 0e83d5
+	size_t offset = req->offset;
Hannes Reinecke 0e83d5
 	int ret;
Hannes Reinecke 0e83d5
 	struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
Hannes Reinecke 0e83d5
 	struct kvec iov = {
Hannes Reinecke 0e83d5
@@ -1066,7 +1067,7 @@ static int nvme_tcp_try_send_ddgst(struct nvme_tcp_request *req)
Hannes Reinecke 0e83d5
 	if (unlikely(ret <= 0))
Hannes Reinecke 0e83d5
 		return ret;
Hannes Reinecke 0e83d5
 
Hannes Reinecke 0e83d5
-	if (req->offset + ret == NVME_TCP_DIGEST_LENGTH) {
Hannes Reinecke 0e83d5
+	if (offset + ret == NVME_TCP_DIGEST_LENGTH) {
Hannes Reinecke 0e83d5
 		nvme_tcp_done_send_req(queue);
Hannes Reinecke 0e83d5
 		return 1;
Hannes Reinecke 0e83d5
 	}
Hannes Reinecke 0e83d5
-- 
Hannes Reinecke 0e83d5
2.29.2
Hannes Reinecke 0e83d5