summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorCaleb Sander Mateos <csander@purestorage.com>2025-01-24 11:43:10 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-02-27 04:30:20 -0800
commit020c50e314dcdf6b8c5027ff62571547e6da0e0b (patch)
tree49c162c9358f315d6ffe313c11b5899abd09718f /drivers
parent1070154b40bf4fc6316bf7e6eedf6d7e5ac8334d (diff)
downloadlinux-020c50e314dcdf6b8c5027ff62571547e6da0e0b.tar.gz
linux-020c50e314dcdf6b8c5027ff62571547e6da0e0b.tar.bz2
linux-020c50e314dcdf6b8c5027ff62571547e6da0e0b.zip
nvme-tcp: fix connect failure on receiving partial ICResp PDU
[ Upstream commit 578539e0969028f711c34d9a4565931edfe1d730 ] nvme_tcp_init_connection() attempts to receive an ICResp PDU but only checks that the return value from recvmsg() is non-negative. If the sender closes the TCP connection or sends fewer than 128 bytes, this check will pass even though the full PDU wasn't received. Ensure the full ICResp PDU is received by checking that recvmsg() returns the expected 128 bytes. Additionally set the MSG_WAITALL flag for recvmsg(), as a sender could split the ICResp over multiple TCP frames. Without MSG_WAITALL, recvmsg() could return prematurely with only part of the PDU. Fixes: 3f2304f8c6d6 ("nvme-tcp: add NVMe over TCP host driver") Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/nvme/host/tcp.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 34eb3dabdc8a..840ae475074d 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1449,11 +1449,14 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue)
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
}
+ msg.msg_flags = MSG_WAITALL;
ret = kernel_recvmsg(queue->sock, &msg, &iov, 1,
iov.iov_len, msg.msg_flags);
- if (ret < 0) {
+ if (ret < sizeof(*icresp)) {
pr_warn("queue %d: failed to receive icresp, error %d\n",
nvme_tcp_queue_id(queue), ret);
+ if (ret >= 0)
+ ret = -ECONNRESET;
goto free_icresp;
}
ret = -ENOTCONN;