nvme: fix handling of tls alerts

Paul Moses p at 1g4.org
Sun Apr 12 18:53:47 PDT 2026


>   (+linux-nvme)
> 

> 
> Hannes,
> 
> can you look at the tls code and provide an input ?
> 
> -ck
> 

> Enclosed is only the splat and repro below, any patch I could produce will be
> derivative of Olga's, so I'll leave the opportunity to them or maintainers.

> https://lore.kernel.org/stable/20250729164023.46643-4-okorniev@redhat.com/

Adding the missing context.

>From previous conversions, it seemed plausible that a fix for this
already exists, so I decided to wait for more info.

I'll send the patch out properly with credit to Olga too, I don't
care. Would I put co-author in that case?

Thanks, 
Paul

>From 06f541d70f5f7efb832c466faeb4bd8f37936dad Mon Sep 17 00:00:00 2001
From: Paul Moses <p at 1g4.org>
Date: Sun, 12 Apr 2026 01:02:07 -0500
Subject: [PATCH] nvmet-tcp: rewind kvec iterators before TLS alert parsing

nvmet_tcp_tls_record_ok() may call tls_alert_recv(), which reads
msg->msg_iter.kvec. The kvec-based receive paths in nvmet-tcp call
this after recvmsg has already advanced the iterator, so alert parsing
can read past the consumed segment.

Rewind the kvec iterator before parsing TLS alerts in the PDU, digest,
and peek receive paths. The inline data receive path uses a bvec-backed
iterator, so stop arming a control buffer there and fail the queue if a
TLS control message is reported while receiving inline data.

Fixes: a1c5dd8355b1 ("nvmet-tcp: control messages for recvmsg()")
---
 drivers/nvme/target/tcp.c | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
index acc71a26733f..67591428ad23 100644
--- a/drivers/nvme/target/tcp.c
+++ b/drivers/nvme/target/tcp.c
@@ -120,7 +120,6 @@ struct nvmet_tcp_cmd {
 	u32				pdu_len;
 	u32				pdu_recv;
 	int				sg_idx;
-	char				recv_cbuf[CMSG_LEN(sizeof(char))];
 	struct msghdr			recv_msg;
 	struct bio_vec			*iov;
 	u32				flags;
@@ -1189,6 +1188,7 @@ static int nvmet_tcp_try_recv_pdu(struct nvmet_tcp_queue *queue)
 	if (unlikely(len < 0))
 		return len;
 	if (queue->tls_pskid) {
+		iov_iter_revert(&msg.msg_iter, len);
 		ret = nvmet_tcp_tls_record_ok(queue, &msg, cbuf);
 		if (ret < 0)
 			return ret;
@@ -1245,19 +1245,22 @@ static void nvmet_tcp_prep_recv_ddgst(struct nvmet_tcp_cmd *cmd)
 static int nvmet_tcp_try_recv_data(struct nvmet_tcp_queue *queue)
 {
 	struct nvmet_tcp_cmd  *cmd = queue->cmd;
-	int len, ret;
+	int len;
 
 	while (msg_data_left(&cmd->recv_msg)) {
 		len = sock_recvmsg(cmd->queue->sock, &cmd->recv_msg,
 			cmd->recv_msg.msg_flags);
+		if (queue->tls_pskid &&
+		    (cmd->recv_msg.msg_flags & MSG_CTRUNC)) {
+			cmd->recv_msg.msg_flags &= ~(MSG_CTRUNC | MSG_EOR);
+			if (len == 0 || len == -EIO) {
+				pr_err("queue %d: unexpected TLS control message while receiving data\n",
+				       queue->idx);
+				return -EIO;
+			}
+		}
 		if (len <= 0)
 			return len;
-		if (queue->tls_pskid) {
-			ret = nvmet_tcp_tls_record_ok(cmd->queue,
-					&cmd->recv_msg, cmd->recv_cbuf);
-			if (ret < 0)
-				return ret;
-		}
 
 		cmd->pdu_recv += len;
 		cmd->rbytes_done += len;
@@ -1295,6 +1298,7 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue)
 	if (unlikely(len < 0))
 		return len;
 	if (queue->tls_pskid) {
+		iov_iter_revert(&msg.msg_iter, len);
 		ret = nvmet_tcp_tls_record_ok(queue, &msg, cbuf);
 		if (ret < 0)
 			return ret;
@@ -1481,10 +1485,6 @@ static int nvmet_tcp_alloc_cmd(struct nvmet_tcp_queue *queue,
 	if (!c->r2t_pdu)
 		goto out_free_data;
 
-	if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) {
-		c->recv_msg.msg_control = c->recv_cbuf;
-		c->recv_msg.msg_controllen = sizeof(c->recv_cbuf);
-	}
 	c->recv_msg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
 
 	list_add_tail(&c->entry, &queue->free_list);
@@ -1764,6 +1764,7 @@ static int nvmet_tcp_try_peek_pdu(struct nvmet_tcp_queue *queue)
 		return len;
 	}
 
+	iov_iter_revert(&msg.msg_iter, len);
 	ret = nvmet_tcp_tls_record_ok(queue, &msg, cbuf);
 	if (ret < 0)
 		return ret;
-- 
2.53.GIT





More information about the Linux-nvme mailing list