From: "Cédric Le Goater" <clg@redhat.com>
To: qemu-arm@nongnu.org, qemu-devel@nongnu.org
Cc: "Kane Chen" <kane_chen@aspeedtech.com>,
"Jamin Lin" <jamin_lin@aspeedtech.com>,
"Cédric Le Goater" <clg@redhat.com>
Subject: [PULL 4/9] aspeed/hace: Fix mapped address may not be unmapped issue
Date: Tue, 12 May 2026 19:13:49 +0200 [thread overview]
Message-ID: <20260512171354.4183887-5-clg@redhat.com> (raw)
In-Reply-To: <20260512171354.4183887-1-clg@redhat.com>
From: Kane Chen <kane_chen@aspeedtech.com>
In the do_hash_operation, the code may be returned earlier because
hash_prepare_sg_iov or hash_prepare_direct_iov may return a failure.
When this condition is happened, current code flow doesn't go through
later code segments. Finally, it causes the mapped address isn't
unmapped properly.
This change unmaps any mapped addresses when an error occurs,
preventing a resource leak.
Signed-off-by: Kane-Chen-AS <kane_chen@aspeedtech.com>
Reviewed-by: Jamin Lin <jamin_lin@aspeedtech.com>
Link: https://lore.kernel.org/qemu-devel/20260512065002.1516704-2-kane_chen@aspeedtech.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/misc/aspeed_hace.c | 63 ++++++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index 0504d61cbf0a..a322905cb37b 100644
--- a/hw/misc/aspeed_hace.c
+++ b/hw/misc/aspeed_hace.c
@@ -218,8 +218,19 @@ static bool hash_accumulate_len(AspeedHACEState *s, hwaddr plen)
return true;
}
+static void hash_iov_unmap(AspeedHACEState *s, struct iovec *iov,
+ hwaddr *mapped_lens, int iov_count)
+{
+ for (; iov_count > 0; iov_count--) {
+ address_space_unmap(&s->dram_as, iov[iov_count - 1].iov_base,
+ mapped_lens[iov_count - 1], false,
+ mapped_lens[iov_count - 1]);
+ }
+}
+
static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov,
- bool acc_mode, bool *acc_final_request)
+ bool acc_mode, bool *acc_final_request,
+ hwaddr *mapped_lens)
{
uint32_t total_msg_len;
uint32_t pad_offset;
@@ -243,9 +254,11 @@ static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov,
iov[0].iov_base = haddr;
iov_idx = 1;
+ mapped_lens[0] = plen;
if (acc_mode) {
if (!hash_accumulate_len(s, plen)) {
+ hash_iov_unmap(s, iov, mapped_lens, 1);
return -1;
}
@@ -265,7 +278,8 @@ static int hash_prepare_direct_iov(AspeedHACEState *s, struct iovec *iov,
}
static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
- bool acc_mode, bool *acc_final_request)
+ bool acc_mode, bool *acc_final_request,
+ hwaddr *mapped_lens)
{
uint32_t total_msg_len;
uint32_t pad_offset;
@@ -275,6 +289,7 @@ static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
int iov_idx;
hwaddr plen;
void *haddr;
+ int iov_mapped = 0;
src = hash_get_source_addr(s);
for (iov_idx = 0; !(len & SG_LIST_LEN_LAST); iov_idx++) {
@@ -282,7 +297,7 @@ static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Failed to set end of sg list marker\n",
__func__);
- return -1;
+ goto fail;
}
len = address_space_ldl_le(&s->dram_as, src,
@@ -307,15 +322,17 @@ static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
"%s: Unable to map address, sg_addr=0x%x, "
"plen=0x%" HWADDR_PRIx "\n",
__func__, sg_addr, plen);
- return -1;
+ goto fail;
}
src += SG_LIST_ENTRY_SIZE;
iov[iov_idx].iov_base = haddr;
+ iov_mapped = iov_idx + 1;
+ mapped_lens[iov_idx] = plen;
if (acc_mode) {
if (!hash_accumulate_len(s, plen)) {
- return -1;
+ goto fail;
}
if (has_padding(s, &iov[iov_idx], plen, &total_msg_len,
@@ -332,6 +349,10 @@ static int hash_prepare_sg_iov(AspeedHACEState *s, struct iovec *iov,
}
return iov_idx;
+
+fail:
+ hash_iov_unmap(s, iov, mapped_lens, iov_mapped);
+ return -1;
}
static uint64_t hash_get_digest_addr(AspeedHACEState *s)
@@ -350,6 +371,7 @@ static uint64_t hash_get_digest_addr(AspeedHACEState *s)
static void hash_write_digest_and_unmap_iov(AspeedHACEState *s,
struct iovec *iov,
int iov_idx,
+ hwaddr *mapped_lens,
uint8_t *digest_buf,
size_t digest_len)
{
@@ -369,15 +391,12 @@ static void hash_write_digest_and_unmap_iov(AspeedHACEState *s,
hace_hexdump("digest", (char *)digest_buf, digest_len);
}
- for (; iov_idx > 0; iov_idx--) {
- address_space_unmap(&s->dram_as, iov[iov_idx - 1].iov_base,
- iov[iov_idx - 1].iov_len, false,
- iov[iov_idx - 1].iov_len);
- }
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
}
static void hash_execute_non_acc_mode(AspeedHACEState *s, int algo,
- struct iovec *iov, int iov_idx)
+ struct iovec *iov, int iov_idx,
+ hwaddr *mapped_lens)
{
g_autofree uint8_t *digest_buf = NULL;
Error *local_err = NULL;
@@ -389,15 +408,17 @@ static void hash_execute_non_acc_mode(AspeedHACEState *s, int algo,
"%s: qcrypto hash bytesv failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
- hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len);
+ hash_write_digest_and_unmap_iov(s, iov, iov_idx, mapped_lens,
+ digest_buf, digest_len);
}
static void hash_execute_acc_mode(AspeedHACEState *s, int algo,
struct iovec *iov, int iov_idx,
- bool final_request)
+ bool final_request, hwaddr *mapped_lens)
{
g_autofree uint8_t *digest_buf = NULL;
Error *local_err = NULL;
@@ -411,6 +432,7 @@ static void hash_execute_acc_mode(AspeedHACEState *s, int algo,
qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash new failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
}
@@ -419,6 +441,7 @@ static void hash_execute_acc_mode(AspeedHACEState *s, int algo,
qemu_log_mask(LOG_GUEST_ERROR, "%s: qcrypto hash updatev failed : %s",
__func__, error_get_pretty(local_err));
error_free(local_err);
+ hash_iov_unmap(s, iov, mapped_lens, iov_idx);
return;
}
@@ -438,22 +461,25 @@ static void hash_execute_acc_mode(AspeedHACEState *s, int algo,
s->total_req_len = 0;
}
- hash_write_digest_and_unmap_iov(s, iov, iov_idx, digest_buf, digest_len);
+ hash_write_digest_and_unmap_iov(s, iov, iov_idx, mapped_lens,
+ digest_buf, digest_len);
}
static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
bool acc_mode)
{
QEMU_UNINITIALIZED struct iovec iov[ASPEED_HACE_MAX_SG];
+ hwaddr mapped_lens[ASPEED_HACE_MAX_SG] = { 0 };
bool acc_final_request = false;
int iov_idx = -1;
/* Prepares the iov for hashing operations based on the selected mode */
if (sg_mode) {
- iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request);
+ iov_idx = hash_prepare_sg_iov(s, iov, acc_mode, &acc_final_request,
+ mapped_lens);
} else {
iov_idx = hash_prepare_direct_iov(s, iov, acc_mode,
- &acc_final_request);
+ &acc_final_request, mapped_lens);
}
if (iov_idx <= 0) {
@@ -468,9 +494,10 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode,
/* Executes the hash operation */
if (acc_mode) {
- hash_execute_acc_mode(s, algo, iov, iov_idx, acc_final_request);
+ hash_execute_acc_mode(s, algo, iov, iov_idx, acc_final_request,
+ mapped_lens);
} else {
- hash_execute_non_acc_mode(s, algo, iov, iov_idx);
+ hash_execute_non_acc_mode(s, algo, iov, iov_idx, mapped_lens);
}
}
--
2.54.0
next prev parent reply other threads:[~2026-05-12 17:16 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 17:13 [PULL 0/9] aspeed queue Cédric Le Goater
2026-05-12 17:13 ` [PULL 1/9] hw/misc/aspeed_sbc: Add bounds checking for OTP write operations Cédric Le Goater
2026-05-12 17:13 ` [PULL 2/9] aspeed/hace: Fix out-of-bounds read in has_padding() Cédric Le Goater
2026-05-12 17:13 ` [PULL 3/9] aspeed/hace: Prevent total_req_len overflow Cédric Le Goater
2026-05-12 17:13 ` Cédric Le Goater [this message]
2026-05-12 17:13 ` [PULL 5/9] hw/arm: Remove sonorapass-bmc machine Cédric Le Goater
2026-05-12 17:13 ` [PULL 6/9] hw/arm: Remove qcom-dc-scm-v1-bmc and qcom-firework-bmc machines Cédric Le Goater
2026-05-12 17:13 ` [PULL 7/9] hw/arm: Remove fp5280g2-bmc machine Cédric Le Goater
2026-05-12 17:13 ` [PULL 8/9] hw/arm: Remove fby35 machine Cédric Le Goater
2026-05-12 17:13 ` [PULL 9/9] hw/i3c/dw-i3c: Fix BCR/DCR extraction and PID assembly during ENTDAA Cédric Le Goater
2026-05-14 16:26 ` [PULL 0/9] aspeed queue Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260512171354.4183887-5-clg@redhat.com \
--to=clg@redhat.com \
--cc=jamin_lin@aspeedtech.com \
--cc=kane_chen@aspeedtech.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.