[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] x86/mem-paging: correct p2m_mem_paging_prep()'s error handling
commit ecb913be4aaae0e01d6a65e8e1c1ac78816b8809 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Fri May 15 16:01:06 2020 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Fri May 15 16:01:06 2020 +0200 x86/mem-paging: correct p2m_mem_paging_prep()'s error handling Communicating errors from p2m_set_entry() to the caller is not enough: Neither the M2P nor the stats updates should occur in such a case. Instead the allocated page needs to be freed again; for cleanliness reasons also properly take into account _PGC_allocated there. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/arch/x86/mm/p2m.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index 92c5ca6d37..60a061216a 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -1781,7 +1781,7 @@ void p2m_mem_paging_populate(struct domain *d, unsigned long gfn_l) */ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer) { - struct page_info *page; + struct page_info *page = NULL; p2m_type_t p2mt; p2m_access_t a; gfn_t gfn = _gfn(gfn_l); @@ -1816,9 +1816,19 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer) goto out; /* Get a free page */ ret = -ENOMEM; - page = alloc_domheap_page(p2m->domain, 0); + page = alloc_domheap_page(d, 0); if ( unlikely(page == NULL) ) goto out; + if ( unlikely(!get_page(page, d)) ) + { + /* + * The domain can't possibly know about this page yet, so failure + * here is a clear indication of something fishy going on. + */ + domain_crash(d); + page = NULL; + goto out; + } mfn = page_to_mfn(page); page_extant = 0; @@ -1828,7 +1838,6 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer) if ( ret ) { ret = -EFAULT; - put_page(page); /* Don't leak pages */ goto out; } } @@ -1839,13 +1848,24 @@ int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t buffer) ret = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, paging_mode_log_dirty(d) ? p2m_ram_logdirty : p2m_ram_rw, a); - set_gpfn_from_mfn(mfn_x(mfn), gfn_l); + if ( !ret ) + { + set_gpfn_from_mfn(mfn_x(mfn), gfn_l); - if ( !page_extant ) - atomic_dec(&d->paged_pages); + if ( !page_extant ) + atomic_dec(&d->paged_pages); + } out: gfn_unlock(p2m, gfn, 0); + + if ( page ) + { + if ( ret ) + put_page_alloc_ref(page); + put_page(page); + } + return ret; } -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |