Skip to content

Commit 2b353ec

Browse files
pvts-matPlaidCat
authored andcommitted
nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu()
jira VULN-56024 cve CVE-2025-21927 commit-author Maurizio Lombardi <[email protected]> commit ad95bab upstream-diff Removed `nvme_tcp_c2h_term' case from `nvme_tcp_recv_pdu_supported' for the sake of consistency of `nvme_tcp_recv_pdu''s behavior relative to the upstream version, between the cases of proper and improper header. (What could be considered as "`c2h_term' type support" started with 84e0090 commit, not included in `ciqlts8_8''s history, so `nvme_tcp_recv_pdu_supported' in `ciqlts8_8' shouldn't report the `nvme_tcp_c2h_term' type as supported.) nvme_tcp_recv_pdu() doesn't check the validity of the header length. When header digests are enabled, a target might send a packet with an invalid header length (e.g. 255), causing nvme_tcp_verify_hdgst() to access memory outside the allocated area and cause memory corruptions by overwriting it with the calculated digest. Fix this by rejecting packets with an unexpected header length. Fixes: 3f2304f ("nvme-tcp: add NVMe over TCP host driver") Signed-off-by: Maurizio Lombardi <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]> (cherry picked from commit ad95bab) Signed-off-by: Marcin Wcisło <[email protected]>
1 parent f10433c commit 2b353ec

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

drivers/nvme/host/tcp.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,18 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
153153
return queue - queue->ctrl->queues;
154154
}
155155

156+
static inline bool nvme_tcp_recv_pdu_supported(enum nvme_tcp_pdu_type type)
157+
{
158+
switch (type) {
159+
case nvme_tcp_c2h_data:
160+
case nvme_tcp_r2t:
161+
case nvme_tcp_rsp:
162+
return true;
163+
default:
164+
return false;
165+
}
166+
}
167+
156168
static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue)
157169
{
158170
u32 queue_idx = nvme_tcp_queue_id(queue);
@@ -675,6 +687,16 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
675687
return 0;
676688

677689
hdr = queue->pdu;
690+
if (unlikely(hdr->hlen != sizeof(struct nvme_tcp_rsp_pdu))) {
691+
if (!nvme_tcp_recv_pdu_supported(hdr->type))
692+
goto unsupported_pdu;
693+
694+
dev_err(queue->ctrl->ctrl.device,
695+
"pdu type %d has unexpected header length (%d)\n",
696+
hdr->type, hdr->hlen);
697+
return -EPROTO;
698+
}
699+
678700
if (queue->hdr_digest) {
679701
ret = nvme_tcp_verify_hdgst(queue, queue->pdu, hdr->hlen);
680702
if (unlikely(ret))
@@ -698,10 +720,13 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
698720
nvme_tcp_init_recv_ctx(queue);
699721
return nvme_tcp_handle_r2t(queue, (void *)queue->pdu);
700722
default:
701-
dev_err(queue->ctrl->ctrl.device,
702-
"unsupported pdu type (%d)\n", hdr->type);
703-
return -EINVAL;
723+
goto unsupported_pdu;
704724
}
725+
726+
unsupported_pdu:
727+
dev_err(queue->ctrl->ctrl.device,
728+
"unsupported pdu type (%d)\n", hdr->type);
729+
return -EINVAL;
705730
}
706731

707732
static inline void nvme_tcp_end_request(struct request *rq, u16 status)

0 commit comments

Comments
 (0)