Skip to content

Commit ad95bab

Browse files
maurizio-lombardikeithbusch
authored andcommitted
nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu()
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 <mlombard@redhat.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Keith Busch <kbusch@kernel.org>
1 parent afb41b0 commit ad95bab

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

drivers/nvme/host/tcp.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)
217217
return queue - queue->ctrl->queues;
218218
}
219219

220+
static inline bool nvme_tcp_recv_pdu_supported(enum nvme_tcp_pdu_type type)
221+
{
222+
switch (type) {
223+
case nvme_tcp_c2h_term:
224+
case nvme_tcp_c2h_data:
225+
case nvme_tcp_r2t:
226+
case nvme_tcp_rsp:
227+
return true;
228+
default:
229+
return false;
230+
}
231+
}
232+
220233
/*
221234
* Check if the queue is TLS encrypted
222235
*/
@@ -818,6 +831,16 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
818831
return 0;
819832

820833
hdr = queue->pdu;
834+
if (unlikely(hdr->hlen != sizeof(struct nvme_tcp_rsp_pdu))) {
835+
if (!nvme_tcp_recv_pdu_supported(hdr->type))
836+
goto unsupported_pdu;
837+
838+
dev_err(queue->ctrl->ctrl.device,
839+
"pdu type %d has unexpected header length (%d)\n",
840+
hdr->type, hdr->hlen);
841+
return -EPROTO;
842+
}
843+
821844
if (unlikely(hdr->type == nvme_tcp_c2h_term)) {
822845
/*
823846
* C2HTermReq never includes Header or Data digests.
@@ -850,10 +873,13 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,
850873
nvme_tcp_init_recv_ctx(queue);
851874
return nvme_tcp_handle_r2t(queue, (void *)queue->pdu);
852875
default:
853-
dev_err(queue->ctrl->ctrl.device,
854-
"unsupported pdu type (%d)\n", hdr->type);
855-
return -EINVAL;
876+
goto unsupported_pdu;
856877
}
878+
879+
unsupported_pdu:
880+
dev_err(queue->ctrl->ctrl.device,
881+
"unsupported pdu type (%d)\n", hdr->type);
882+
return -EINVAL;
857883
}
858884

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

0 commit comments

Comments
 (0)