Skip to content

Commit a62768f

Browse files
pvts-matPlaidCat
authored andcommitted
nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu()
jira VULN-56023 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_6''s history, so `nvme_tcp_recv_pdu_supported' in `ciqlts8_6' 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 964e01f commit a62768f

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

drivers/nvme/host/tcp.c

+28-3
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
150150
return queue - queue->ctrl->queues;
151151
}
152152

153+
static inline bool nvme_tcp_recv_pdu_supported(enum nvme_tcp_pdu_type type)
154+
{
155+
switch (type) {
156+
case nvme_tcp_c2h_data:
157+
case nvme_tcp_r2t:
158+
case nvme_tcp_rsp:
159+
return true;
160+
default:
161+
return false;
162+
}
163+
}
164+
153165
static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue)
154166
{
155167
u32 queue_idx = nvme_tcp_queue_id(queue);
@@ -663,6 +675,16 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
663675
return 0;
664676

665677
hdr = queue->pdu;
678+
if (unlikely(hdr->hlen != sizeof(struct nvme_tcp_rsp_pdu))) {
679+
if (!nvme_tcp_recv_pdu_supported(hdr->type))
680+
goto unsupported_pdu;
681+
682+
dev_err(queue->ctrl->ctrl.device,
683+
"pdu type %d has unexpected header length (%d)\n",
684+
hdr->type, hdr->hlen);
685+
return -EPROTO;
686+
}
687+
666688
if (queue->hdr_digest) {
667689
ret = nvme_tcp_verify_hdgst(queue, queue->pdu, hdr->hlen);
668690
if (unlikely(ret))
@@ -686,10 +708,13 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
686708
nvme_tcp_init_recv_ctx(queue);
687709
return nvme_tcp_handle_r2t(queue, (void *)queue->pdu);
688710
default:
689-
dev_err(queue->ctrl->ctrl.device,
690-
"unsupported pdu type (%d)\n", hdr->type);
691-
return -EINVAL;
711+
goto unsupported_pdu;
692712
}
713+
714+
unsupported_pdu:
715+
dev_err(queue->ctrl->ctrl.device,
716+
"unsupported pdu type (%d)\n", hdr->type);
717+
return -EINVAL;
693718
}
694719

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

0 commit comments

Comments
 (0)