@samitouri / QOSamiQemu / commits / 283d921e77

hw/ufs: Guard MCQ CQ accesses against missing queues

A guest can ring an MCQ CQ doorbell before the completion queue exists. The CQ head write path then dereferences a NULL CQ through ufs_mcq_cq_full(). Ignore CQ head updates for missing CQs, and make ufs_mcq_cq_full() handle a missing CQ defensively. Fixes: f78762a3cc8 ("hw/ufs: Fix mcq completion queue wraparound") Reported-by: Rayhan Ramdhany Hanaputra <hanaputrarayhan@gmail.com> Cc: qemu-stable@nongnu.org Signed-off-by: Jeuk Kim <jeuk20.kim@samsung.com>

Jeuk Kim committed Mar 16, 2026 at 14:39 UTC 283d921e771e8a98a5c3d1eed1ed791b89ba47a8
2 files changed +12 -1
hw/ufs/ufs.c
+4
@@ -817,6 +817,10 @@ static void ufs_write_mcq_op_reg(UfsHc *u, hwaddr offset, uint32_t data,
817 case offsetof(UfsMcqOpReg, cq.hp): {
818 UfsCq *cq = u->cq[qid];
819
820 + if (!cq) {
821 + break;
822 + }
823 +
824 if (ufs_mcq_cq_full(u, qid) && !QTAILQ_EMPTY(&cq->req_list)) {
825 /* Enqueueing to CQ was blocked because it was full */
826 qemu_bh_schedule(cq->bh);
hw/ufs/ufs.h
+8 -1
@@ -203,7 +203,14 @@ static inline bool ufs_mcq_cq_empty(UfsHc *u, uint32_t qid)
203 static inline bool ufs_mcq_cq_full(UfsHc *u, uint32_t qid)
204 {
205 uint32_t tail = ufs_mcq_cq_tail(u, qid);
206 - uint16_t cq_size = u->cq[qid]->size;
206 + UfsCq *cq = u->cq[qid];
207 + uint16_t cq_size;
208 +
209 + if (!cq) {
210 + return false;
211 + }
212 +
213 + cq_size = cq->size;
214
215 tail = (tail + sizeof(UfsCqEntry)) % (sizeof(UfsCqEntry) * cq_size);
216 return tail == ufs_mcq_cq_head(u, qid);