From: Jeuk Kim <[email protected]>
A guest can program an out-of-range SQATTR.CQID value, or ring an
MCQ SQ doorbell before the submission queue exists.
Reject SQ creation when the referenced CQ is invalid, and ignore SQ
doorbells for queues that have not been created. This prevents a
guest-triggerable out-of-bounds read and NULL pointer dereference.
Fixes: 5c079578d2e ("hw/ufs: Add support MCQ of UFSHCI 4.0")
Reported-by: Rayhan Ramdhany Hanaputra <[email protected]>
Cc: [email protected]
Signed-off-by: Jeuk Kim <[email protected]>
---
hw/ufs/ufs.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/hw/ufs/ufs.c b/hw/ufs/ufs.c
index cb74cb56bc..d5fba15e2a 100644
--- a/hw/ufs/ufs.c
+++ b/hw/ufs/ufs.c
@@ -517,8 +517,13 @@ static bool ufs_mcq_create_sq(UfsHc *u, uint8_t qid,
uint32_t attr)
return false;
}
+ if (cqid >= u->params.mcq_maxq) {
+ trace_ufs_err_mcq_create_sq_invalid_cqid(cqid);
+ return false;
+ }
+
if (!u->cq[cqid]) {
- trace_ufs_err_mcq_create_sq_invalid_cqid(qid);
+ trace_ufs_err_mcq_create_sq_invalid_cqid(cqid);
return false;
}
@@ -775,6 +780,11 @@ static void ufs_mcq_process_db(UfsHc *u, uint8_t qid,
uint32_t db)
}
sq = u->sq[qid];
+ if (!sq) {
+ trace_ufs_err_mcq_db_wr_invalid_sqid(qid);
+ return;
+ }
+
if (sq->size * sizeof(UfsSqEntry) <= db) {
trace_ufs_err_mcq_db_wr_invalid_db(qid, db);
return;
@@ -788,7 +798,14 @@ static void ufs_write_mcq_op_reg(UfsHc *u, hwaddr offset,
uint32_t data,
unsigned size)
{
int qid = offset / sizeof(UfsMcqOpReg);
- UfsMcqOpReg *opr = &u->mcq_op_reg[qid];
+ UfsMcqOpReg *opr;
+
+ if (qid >= u->params.mcq_maxq) {
+ trace_ufs_err_invalid_register_offset(offset);
+ return;
+ }
+
+ opr = &u->mcq_op_reg[qid];
switch (offset % sizeof(UfsMcqOpReg)) {
case offsetof(UfsMcqOpReg, sq.tp):
--
2.43.0