|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] xen/arm: Fix memory leak in xenmem_add_to_physmap_one
When a guest maps pages via XENMEM_add_to_physmap to a GFN that already
has an existing mapping, the old page at that GFN was not being removed,
causing a memory leak. This affects all mapping spaces including
XENMAPSPACE_shared_info, XENMAPSPACE_grant_table, and
XENMAPSPACE_gmfn_foreign. The memory would be reclaimed on domain
destruction.
Add logic to remove the previously mapped page before creating the new
mapping, matching the x86 implementation approach.
Additionally, skip removal if the same MFN is being remapped.
Signed-off-by: Michal Orzel <michal.orzel@xxxxxxx>
---
I'm not sure where to point the Fixes tag to.
---
xen/arch/arm/mm.c | 32 +++++++++++++++++++++++++++++---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 6df8b616e464..b9f1a493dcd7 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -166,10 +166,11 @@ int xenmem_add_to_physmap_one(
unsigned long idx,
gfn_t gfn)
{
- mfn_t mfn = INVALID_MFN;
+ mfn_t mfn = INVALID_MFN, mfn_old;
int rc;
p2m_type_t t;
struct page_info *page = NULL;
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
switch ( space )
{
@@ -244,6 +245,33 @@ int xenmem_add_to_physmap_one(
return -ENOSYS;
}
+ /*
+ * Remove previously mapped page if it was present, to avoid leaking
+ * memory.
+ */
+ mfn_old = gfn_to_mfn(d, gfn);
+
+ if ( mfn_valid(mfn_old) )
+ {
+ if ( is_special_page(mfn_to_page(mfn_old)) )
+ {
+ /* Just unmap, don't free */
+ p2m_write_lock(p2m);
+ rc = p2m_set_entry(p2m, gfn, 1, INVALID_MFN,
+ p2m_invalid, p2m->default_access);
+ p2m_write_unlock(p2m);
+ if ( rc )
+ return rc;
+ }
+ else if ( !mfn_eq(mfn, mfn_old) )
+ {
+ /* Normal domain memory is freed, to avoid leaking memory */
+ rc = guest_remove_page(d, gfn_x(gfn));
+ if ( rc )
+ return rc;
+ }
+ }
+
/*
* Map at new location. Here we need to map xenheap RAM page differently
* because we need to store the valid GFN and make sure that nothing was
@@ -255,8 +283,6 @@ int xenmem_add_to_physmap_one(
rc = guest_physmap_add_entry(d, gfn, mfn, 0, t);
else
{
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
-
p2m_write_lock(p2m);
if ( gfn_eq(page_get_xenheap_gfn(mfn_to_page(mfn)), INVALID_GFN) )
{
--
2.43.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |