In accumulate mode, total_req_len is incremented with plen (hwaddr) for each hash request. Repeated additions can overflow total_req_len (uint32_t) and potentially bypass validation checks in has_padding().
Add a helper function to detect overflow before incrementing total_req_len and reject the request if overflow would occur. 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]> --- hw/misc/aspeed_hace.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index ef698b3ecb72..0504d61cbf0a 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -205,6 +205,19 @@ static uint64_t hash_get_source_addr(AspeedHACEState *s) return src_addr; } +static bool hash_accumulate_len(AspeedHACEState *s, hwaddr plen) +{ + if (plen > UINT32_MAX - s->total_req_len) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: total_req_len overflow, current=0x%x, adding=0x%" + HWADDR_PRIx "\n", __func__, s->total_req_len, plen); + return false; + } + + s->total_req_len += plen; + return true; +} + static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov, bool acc_mode, bool *acc_final_request) { @@ -232,7 +245,9 @@ static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov, iov_idx = 1; if (acc_mode) { - s->total_req_len += plen; + if (!hash_accumulate_len(s, plen)) { + return -1; + } if (has_padding(s, &iov[0], plen, &total_msg_len, &pad_offset)) { @@ -299,7 +314,9 @@ static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov, iov[iov_idx].iov_base = haddr; if (acc_mode) { - s->total_req_len += plen; + if (!hash_accumulate_len(s, plen)) { + return -1; + } if (has_padding(s, &iov[iov_idx], plen, &total_msg_len, &pad_offset)) { -- 2.54.0
