@samitouri / QOSamiQemu / commits / eb5cc99aff

hw/nvme: fix heap-buffer-overflow in nvme_abort

In nvme_abort(), the submission queue pointer is dereferenced from the guest-controlled sqid before validating it with nvme_check_sqid(): NvmeSQueue *sq = n->sq[sqid]; Since sqid is a 16-bit value (range 0-65535) taken directly from CDW10, and n->sq[] is typically only max_ioqpairs+1 (65) entries, a malicious guest can trigger an out-of-bounds heap read by sending an Abort command with a large sqid. ASan reports this as heap-buffer-overflow in nvme_abort. Fix this by moving the array dereference to after the nvme_check_sqid() bounds validation. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3348 Fixes: 75209c071a ("hw/nvme: actually implement abort") Cc: qemu-stable@nongnu.org Signed-off-by: Kaixuan Li <kaixuanli@ntu.edu.sg> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>

Kaixuan Li committed Mar 19, 2026 at 10:46 UTC eb5cc99aff17cbfdad16b18d3503c6f22233eeb5
1 file changed +3 -1
hw/nvme/ctrl.c
+3 -1
@@ -6111,7 +6111,7 @@ static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req)
6111 {
6112 uint16_t sqid = le32_to_cpu(req->cmd.cdw10) & 0xffff;
6113 uint16_t cid = (le32_to_cpu(req->cmd.cdw10) >> 16) & 0xffff;
6114 - NvmeSQueue *sq = n->sq[sqid];
6114 + NvmeSQueue *sq;
6115 NvmeRequest *r, *next;
6116 int i;
6117
@@ -6120,6 +6120,8 @@ static uint16_t nvme_abort(NvmeCtrl *n, NvmeRequest *req)
6120 return NVME_INVALID_FIELD | NVME_DNR;
6121 }
6122
6123 + sq = n->sq[sqid];
6124 +
6125 if (sqid == 0) {
6126 for (i = 0; i < n->outstanding_aers; i++) {
6127 NvmeRequest *re = n->aer_reqs[i];