git: 1397c8ebb7ef - stable/13 - nvme: Sanity check completion id

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Fri, 21 Jan 2022 02:26:54 UTC
The branch stable/13 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=1397c8ebb7ef4da83bd2d4fd3a2d4a7725075480

commit 1397c8ebb7ef4da83bd2d4fd3a2d4a7725075480
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2021-09-29 03:21:50 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2022-01-21 02:07:30 +0000

    nvme: Sanity check completion id
    
    Make sure the completion ID is in the range of [0..num_trackers) since
    the values past the end of the act_tr array are never going to be valid
    trackers and will lead to pain and suffering if we try to dereference
    them to get the tracker or to set the tracker back to NULL as we
    complete the I/O.
    
    Sponsored by:           Netflix
    Reviewed by:            mav, chs, chuck
    Differential Revision:  https://reviews.freebsd.org/D32088
    
    (cherry picked from commit 36a87d0c6fe9d65de23f177ef84000b205f87e39)
---
 sys/dev/nvme/nvme_qpair.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
index 788322092f88..8041731099df 100644
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -624,7 +624,10 @@ nvme_qpair_process_completions(struct nvme_qpair *qpair)
 		    NVME_STATUS_GET_P(status) == NVME_STATUS_GET_P(cpl.status),
 		    ("Phase unexpectedly inconsistent"));
 
-		tr = qpair->act_tr[cpl.cid];
+		if (cpl.cid < qpair->num_trackers)
+			tr = qpair->act_tr[cpl.cid];
+		else
+			tr = NULL;
 
 		if (tr != NULL) {
 			nvme_qpair_complete_tracker(tr, &cpl, ERROR_PRINT_ALL);
@@ -644,7 +647,8 @@ nvme_qpair_process_completions(struct nvme_qpair *qpair)
 			 * ignore this condition because it's not unexpected.
 			 */
 			nvme_printf(qpair->ctrlr,
-			    "cpl does not map to outstanding cmd\n");
+			    "cpl (cid = %u) does not map to outstanding cmd\n",
+				cpl.cid);
 			/* nvme_dump_completion expects device endianess */
 			nvme_dump_completion(&qpair->cpl[qpair->cq_head]);
 			KASSERT(0, ("received completion for unknown cmd"));