]> www.infradead.org Git - nvme.git/commitdiff
nvme-tcp: fix connect failure on receiving partial ICResp PDU
authorCaleb Sander Mateos <csander@purestorage.com>
Fri, 24 Jan 2025 18:43:10 +0000 (11:43 -0700)
committerKeith Busch <kbusch@kernel.org>
Tue, 18 Feb 2025 15:37:02 +0000 (07:37 -0800)
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>
drivers/nvme/host/tcp.c

index a7398e9e5f71cadb7f5d9173344c1ccffcc6b738..8a9131c95a3daedc8672f889d267293c21fccb05 100644 (file)
@@ -1492,11 +1492,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;