Merge tag 'mem-staging-pull-request' of https://gitlab.com/peterx/qemu into staging

Memory pull for 10.2

- Peter's fix on flatview_access_allowed()
- Peter's fix on MR circular ref

# -----BEGIN PGP SIGNATURE-----
#
# iIgEABYKADAWIQS5GE3CDMRX2s990ak7X8zN86vXBgUCaMg4oxIccGV0ZXJ4QHJl
# ZGhhdC5jb20ACgkQO1/MzfOr1wYeLAD+LQ44LdRTjbdlAbDjSNnCorfEBFUmNysK
# St4ut4Z9ZzAA+gK8DO12zc41Oi51NaBdD+X0s94DCV4UFl4Cz1D8HoIF
# =hAUJ
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 15 Sep 2025 09:02:43 AM PDT
# gpg:                using EDDSA key B9184DC20CC457DACF7DD1A93B5FCCCDF3ABD706
# gpg:                issuer "peterx@redhat.com"
# gpg: Good signature from "Peter Xu <xzpeter@gmail.com>" [unknown]
# gpg:                 aka "Peter Xu <peterx@redhat.com>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B918 4DC2 0CC4 57DA CF7D  D1A9 3B5F CCCD F3AB D706

* tag 'mem-staging-pull-request' of https://gitlab.com/peterx/qemu:
  memory: Fix leaks due to owner-shared MRs circular references
  memory: Fix addr/len for flatview_access_allowed()

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2025-09-16 10:09:59 -07:00
3 changed files with 44 additions and 13 deletions
+5 -2
View File
@@ -158,8 +158,11 @@ ioeventfd) can be changed during the region lifecycle. They take effect
as soon as the region is made visible. This can be immediately, later,
or never.
Destruction of a memory region happens automatically when the owner
object dies.
Destruction of a memory region happens automatically when the owner object
dies. When there are multiple memory regions under the same owner object,
the memory API will guarantee all memory regions will be properly detached
and finalized one by one. The order in which memory regions will be
finalized is not guaranteed.
If however the memory region is part of a dynamically allocated data
structure, you should call object_unparent() to destroy the memory region
+37 -9
View File
@@ -1796,16 +1796,37 @@ static void memory_region_finalize(Object *obj)
{
MemoryRegion *mr = MEMORY_REGION(obj);
assert(!mr->container);
/* We know the region is not visible in any address space (it
* does not have a container and cannot be a root either because
* it has no references, so we can blindly clear mr->enabled.
* memory_region_set_enabled instead could trigger a transaction
* and cause an infinite loop.
/*
* Each memory region (that can be freed) must have an owner, and it
* always has the same lifecycle of its owner. It means when reaching
* here, the memory region's owner's refcount is zero.
*
* Here it is possible that the MR has:
*
* (1) mr->container set, which means this MR is a subregion of a
* container MR. In this case they must share the same owner as the
* container (otherwise the container should have kept a refcount
* of this MR's owner).
*
* (2) mr->subregions non-empty, which means this MR is a container of
* one or more other MRs (which might have the the owner as this
* MR, or a different owner).
*
* We know the MR, or any MR that is attached to this one as either
* container or children, is not visible in any address space, because
* otherwise the address space should have taken at least one refcount
* of this MR's owner. So we can blindly clear mr->enabled.
*
* memory_region_set_enabled instead could trigger a transaction and
* cause an infinite loop.
*/
mr->enabled = false;
memory_region_transaction_begin();
if (mr->container) {
/* Must share the owner; see above comments */
assert(mr->container->owner == mr->owner);
memory_region_del_subregion(mr->container, mr);
}
while (!QTAILQ_EMPTY(&mr->subregions)) {
MemoryRegion *subregion = QTAILQ_FIRST(&mr->subregions);
memory_region_del_subregion(mr, subregion);
@@ -2640,7 +2661,10 @@ static void memory_region_update_container_subregions(MemoryRegion *subregion)
memory_region_transaction_begin();
memory_region_ref(subregion);
if (mr->owner != subregion->owner) {
memory_region_ref(subregion);
}
QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
if (subregion->priority >= other->priority) {
QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
@@ -2698,7 +2722,11 @@ void memory_region_del_subregion(MemoryRegion *mr,
assert(alias->mapped_via_alias >= 0);
}
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
memory_region_unref(subregion);
if (mr->owner != subregion->owner) {
memory_region_unref(subregion);
}
memory_region_update_pending |= mr->enabled && subregion->enabled;
memory_region_transaction_commit();
}
+2 -2
View File
@@ -3027,7 +3027,7 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
l = len;
mr = flatview_translate(fv, addr, &mr_addr, &l, true, attrs);
if (!flatview_access_allowed(mr, attrs, addr, len)) {
if (!flatview_access_allowed(mr, attrs, mr_addr, l)) {
return MEMTX_ACCESS_ERROR;
}
return flatview_write_continue(fv, addr, attrs, buf, len,
@@ -3118,7 +3118,7 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
l = len;
mr = flatview_translate(fv, addr, &mr_addr, &l, false, attrs);
if (!flatview_access_allowed(mr, attrs, addr, len)) {
if (!flatview_access_allowed(mr, attrs, mr_addr, l)) {
return MEMTX_ACCESS_ERROR;
}
return flatview_read_continue(fv, addr, attrs, buf, len,