From: Cédric Le Goater <[email protected]> The has_padding() function reads the last 8 bytes of a DMA buffer without validating req_len. req_len is guest-controlled (via R_HASH_SRC_LEN register or scatter-gather entries) and values less than 8 cause integer underflow. This can result in an out-of-bounds read of QEMU process memory.
Add a check to ensure req_len >= 8 before accessing the buffer. Reported-by: Katherine Leaver <[email protected]> Cc: [email protected] Fixes: 5cd7d8564a8b ("aspeed/hace: Support AST2600 HACE") Link: https://lore.kernel.org/qemu-devel/[email protected] Signed-off-by: Cédric Le Goater <[email protected]> (cherry picked from commit 534a52755befa7b8d49c921f8dc964185903efae) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index 96997a03fc..212703cbe4 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -112,6 +112,14 @@ static bool has_padding(AspeedHACEState *s, struct iovec *iov, hwaddr req_len, uint32_t *total_msg_len, uint32_t *pad_offset) { + /* Need at least 8 bytes to read the total message length field */ + if (req_len < 8) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid request length=0x%" HWADDR_PRIx "\n", + __func__, req_len); + return false; + } + *total_msg_len = (uint32_t)(ldq_be_p(iov->iov_base + req_len - 8) / 8); /* * SG_LIST_LEN_LAST asserted in the request length doesn't mean it is the -- 2.47.3
