From: Cédric Le Goater <clg@redhat.com>
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 <katherine.j.leaver@gmail.com>
Cc: qemu-stable@nongnu.org
Fixes: 5cd7d8564a8b ("aspeed/hace: Support AST2600 HACE")
Link: https://lore.kernel.org/qemu-devel/20260504213421.710035-3-clg@redhat.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
(cherry picked from commit c6aa2d0ac161f2a58a8fbab9a15e846278661158)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index c7a2731e38..f08b7ae376 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.47.3