|
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 |
|