diff options
Diffstat (limited to 'system/xen/xsa/xsa222-2-4.8.patch')
-rw-r--r-- | system/xen/xsa/xsa222-2-4.8.patch | 405 |
1 files changed, 0 insertions, 405 deletions
diff --git a/system/xen/xsa/xsa222-2-4.8.patch b/system/xen/xsa/xsa222-2-4.8.patch deleted file mode 100644 index 2825d2a061..0000000000 --- a/system/xen/xsa/xsa222-2-4.8.patch +++ /dev/null @@ -1,405 +0,0 @@ -From: Jan Beulich <jbeulich@suse.com> -Subject: guest_physmap_remove_page() needs its return value checked - -Callers, namely such subsequently freeing the page, must not blindly -assume success - the function may namely fail when needing to shatter a -super page, but there not being memory available for the then needed -intermediate page table. - -As it happens, guest_remove_page() callers now also all check the -return value. - -Furthermore a missed put_gfn() on an error path in gnttab_transfer() is -also being taken care of. - -This is part of XSA-222. - -Reported-by: Julien Grall <julien.grall@arm.com> -Signed-off-by: Jan Beulich <jbeulich@suse.com> -Signed-off-by: Julien Grall <julien.grall@arm.com> -Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> - ---- a/xen/arch/arm/mm.c -+++ b/xen/arch/arm/mm.c -@@ -1340,13 +1340,14 @@ int replace_grant_host_mapping(unsigned - { - gfn_t gfn = _gfn(addr >> PAGE_SHIFT); - struct domain *d = current->domain; -+ int rc; - - if ( new_addr != 0 || (flags & GNTMAP_contains_pte) ) - return GNTST_general_error; - -- guest_physmap_remove_page(d, gfn, _mfn(mfn), 0); -+ rc = guest_physmap_remove_page(d, gfn, _mfn(mfn), 0); - -- return GNTST_okay; -+ return rc ? GNTST_general_error : GNTST_okay; - } - - int is_iomem_page(unsigned long mfn) ---- a/xen/arch/arm/p2m.c -+++ b/xen/arch/arm/p2m.c -@@ -1211,11 +1211,10 @@ int guest_physmap_add_entry(struct domai - return p2m_insert_mapping(d, gfn, (1 << page_order), mfn, t); - } - --void guest_physmap_remove_page(struct domain *d, -- gfn_t gfn, -- mfn_t mfn, unsigned int page_order) -+int guest_physmap_remove_page(struct domain *d, gfn_t gfn, mfn_t mfn, -+ unsigned int page_order) - { -- p2m_remove_mapping(d, gfn, (1 << page_order), mfn); -+ return p2m_remove_mapping(d, gfn, (1 << page_order), mfn); - } - - static int p2m_alloc_table(struct domain *d) ---- a/xen/arch/x86/domain.c -+++ b/xen/arch/x86/domain.c -@@ -808,7 +808,15 @@ int arch_domain_soft_reset(struct domain - ret = -ENOMEM; - goto exit_put_gfn; - } -- guest_physmap_remove_page(d, _gfn(gfn), _mfn(mfn), PAGE_ORDER_4K); -+ -+ ret = guest_physmap_remove_page(d, _gfn(gfn), _mfn(mfn), PAGE_ORDER_4K); -+ if ( ret ) -+ { -+ printk(XENLOG_G_ERR "Failed to remove Dom%d's shared_info frame %lx\n", -+ d->domain_id, gfn); -+ free_domheap_page(new_page); -+ goto exit_put_gfn; -+ } - - ret = guest_physmap_add_page(d, _gfn(gfn), _mfn(page_to_mfn(new_page)), - PAGE_ORDER_4K); ---- a/xen/arch/x86/domain_build.c -+++ b/xen/arch/x86/domain_build.c -@@ -427,7 +427,9 @@ static __init void pvh_add_mem_mapping(s - if ( !iomem_access_permitted(d, mfn + i, mfn + i) ) - { - omfn = get_gfn_query_unlocked(d, gfn + i, &t); -- guest_physmap_remove_page(d, _gfn(gfn + i), omfn, PAGE_ORDER_4K); -+ if ( guest_physmap_remove_page(d, _gfn(gfn + i), omfn, -+ PAGE_ORDER_4K) ) -+ /* nothing, best effort only */; - continue; - } - ---- a/xen/arch/x86/hvm/ioreq.c -+++ b/xen/arch/x86/hvm/ioreq.c -@@ -267,8 +267,9 @@ bool_t is_ioreq_server_page(struct domai - static void hvm_remove_ioreq_gmfn( - struct domain *d, struct hvm_ioreq_page *iorp) - { -- guest_physmap_remove_page(d, _gfn(iorp->gmfn), -- _mfn(page_to_mfn(iorp->page)), 0); -+ if ( guest_physmap_remove_page(d, _gfn(iorp->gmfn), -+ _mfn(page_to_mfn(iorp->page)), 0) ) -+ domain_crash(d); - clear_page(iorp->va); - } - ---- a/xen/arch/x86/mm.c -+++ b/xen/arch/x86/mm.c -@@ -4276,7 +4276,11 @@ static int replace_grant_p2m_mapping( - type, mfn_x(old_mfn), frame); - return GNTST_general_error; - } -- guest_physmap_remove_page(d, _gfn(gfn), _mfn(frame), PAGE_ORDER_4K); -+ if ( guest_physmap_remove_page(d, _gfn(gfn), _mfn(frame), PAGE_ORDER_4K) ) -+ { -+ put_gfn(d, gfn); -+ return GNTST_general_error; -+ } - - put_gfn(d, gfn); - return GNTST_okay; -@@ -4798,7 +4802,7 @@ int xenmem_add_to_physmap_one( - struct page_info *page = NULL; - unsigned long gfn = 0; /* gcc ... */ - unsigned long prev_mfn, mfn = 0, old_gpfn; -- int rc; -+ int rc = 0; - p2m_type_t p2mt; - - switch ( space ) -@@ -4872,25 +4876,30 @@ int xenmem_add_to_physmap_one( - { - if ( is_xen_heap_mfn(prev_mfn) ) - /* Xen heap frames are simply unhooked from this phys slot. */ -- guest_physmap_remove_page(d, gpfn, _mfn(prev_mfn), PAGE_ORDER_4K); -+ rc = guest_physmap_remove_page(d, gpfn, _mfn(prev_mfn), PAGE_ORDER_4K); - else - /* Normal domain memory is freed, to avoid leaking memory. */ -- guest_remove_page(d, gfn_x(gpfn)); -+ rc = guest_remove_page(d, gfn_x(gpfn)); - } - /* In the XENMAPSPACE_gmfn case we still hold a ref on the old page. */ - put_gfn(d, gfn_x(gpfn)); - -+ if ( rc ) -+ goto put_both; -+ - /* Unmap from old location, if any. */ - old_gpfn = get_gpfn_from_mfn(mfn); - ASSERT( old_gpfn != SHARED_M2P_ENTRY ); - if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range ) - ASSERT( old_gpfn == gfn ); - if ( old_gpfn != INVALID_M2P_ENTRY ) -- guest_physmap_remove_page(d, _gfn(old_gpfn), _mfn(mfn), PAGE_ORDER_4K); -+ rc = guest_physmap_remove_page(d, _gfn(old_gpfn), _mfn(mfn), PAGE_ORDER_4K); - - /* Map at new location. */ -- rc = guest_physmap_add_page(d, gpfn, _mfn(mfn), PAGE_ORDER_4K); -+ if ( !rc ) -+ rc = guest_physmap_add_page(d, gpfn, _mfn(mfn), PAGE_ORDER_4K); - -+ put_both: - /* In the XENMAPSPACE_gmfn, we took a ref of the gfn at the top */ - if ( space == XENMAPSPACE_gmfn || space == XENMAPSPACE_gmfn_range ) - put_gfn(d, gfn); ---- a/xen/arch/x86/mm/p2m.c -+++ b/xen/arch/x86/mm/p2m.c -@@ -2925,10 +2925,12 @@ int p2m_add_foreign(struct domain *tdom, - { - if ( is_xen_heap_mfn(mfn_x(prev_mfn)) ) - /* Xen heap frames are simply unhooked from this phys slot */ -- guest_physmap_remove_page(tdom, _gfn(gpfn), prev_mfn, 0); -+ rc = guest_physmap_remove_page(tdom, _gfn(gpfn), prev_mfn, 0); - else - /* Normal domain memory is freed, to avoid leaking memory. */ -- guest_remove_page(tdom, gpfn); -+ rc = guest_remove_page(tdom, gpfn); -+ if ( rc ) -+ goto put_both; - } - /* - * Create the new mapping. Can't use guest_physmap_add_page() because it -@@ -2941,6 +2943,7 @@ int p2m_add_foreign(struct domain *tdom, - "gpfn:%lx mfn:%lx fgfn:%lx td:%d fd:%d\n", - gpfn, mfn_x(mfn), fgfn, tdom->domain_id, fdom->domain_id); - -+ put_both: - put_page(page); - - /* ---- a/xen/common/grant_table.c -+++ b/xen/common/grant_table.c -@@ -1768,6 +1768,7 @@ gnttab_transfer( - for ( i = 0; i < count; i++ ) - { - bool_t okay; -+ int rc; - - if (i && hypercall_preempt_check()) - return i; -@@ -1818,27 +1819,33 @@ gnttab_transfer( - goto copyback; - } - -- guest_physmap_remove_page(d, _gfn(gop.mfn), _mfn(mfn), 0); -+ rc = guest_physmap_remove_page(d, _gfn(gop.mfn), _mfn(mfn), 0); - gnttab_flush_tlb(d); -+ if ( rc ) -+ { -+ gdprintk(XENLOG_INFO, -+ "gnttab_transfer: can't remove GFN %"PRI_xen_pfn" (MFN %lx)\n", -+ gop.mfn, mfn); -+ gop.status = GNTST_general_error; -+ goto put_gfn_and_copyback; -+ } - - /* Find the target domain. */ - if ( unlikely((e = rcu_lock_domain_by_id(gop.domid)) == NULL) ) - { -- put_gfn(d, gop.mfn); - gdprintk(XENLOG_INFO, "gnttab_transfer: can't find domain %d\n", - gop.domid); -- page->count_info &= ~(PGC_count_mask|PGC_allocated); -- free_domheap_page(page); - gop.status = GNTST_bad_domain; -- goto copyback; -+ goto put_gfn_and_copyback; - } - - if ( xsm_grant_transfer(XSM_HOOK, d, e) ) - { -- put_gfn(d, gop.mfn); - gop.status = GNTST_permission_denied; - unlock_and_copyback: - rcu_unlock_domain(e); -+ put_gfn_and_copyback: -+ put_gfn(d, gop.mfn); - page->count_info &= ~(PGC_count_mask|PGC_allocated); - free_domheap_page(page); - goto copyback; -@@ -1887,12 +1894,8 @@ gnttab_transfer( - "Transferee (d%d) has no headroom (tot %u, max %u)\n", - e->domain_id, e->tot_pages, e->max_pages); - -- rcu_unlock_domain(e); -- put_gfn(d, gop.mfn); -- page->count_info &= ~(PGC_count_mask|PGC_allocated); -- free_domheap_page(page); - gop.status = GNTST_general_error; -- goto copyback; -+ goto unlock_and_copyback; - } - - /* Okay, add the page to 'e'. */ -@@ -1921,13 +1924,8 @@ gnttab_transfer( - - if ( drop_dom_ref ) - put_domain(e); -- rcu_unlock_domain(e); -- -- put_gfn(d, gop.mfn); -- page->count_info &= ~(PGC_count_mask|PGC_allocated); -- free_domheap_page(page); - gop.status = GNTST_general_error; -- goto copyback; -+ goto unlock_and_copyback; - } - - page_list_add_tail(page, &e->page_list); ---- a/xen/common/memory.c -+++ b/xen/common/memory.c -@@ -272,8 +272,12 @@ int guest_remove_page(struct domain *d, - mfn = get_gfn_query(d, gmfn, &p2mt); - if ( unlikely(p2m_is_paging(p2mt)) ) - { -- guest_physmap_remove_page(d, _gfn(gmfn), mfn, 0); -+ rc = guest_physmap_remove_page(d, _gfn(gmfn), mfn, 0); - put_gfn(d, gmfn); -+ -+ if ( rc ) -+ return rc; -+ - /* If the page hasn't yet been paged out, there is an - * actual page that needs to be released. */ - if ( p2mt == p2m_ram_paging_out ) -@@ -337,7 +341,9 @@ int guest_remove_page(struct domain *d, - return -ENXIO; - } - -- if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) -+ rc = guest_physmap_remove_page(d, _gfn(gmfn), mfn, 0); -+ -+ if ( !rc && test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) - put_page_and_type(page); - - /* -@@ -348,16 +354,14 @@ int guest_remove_page(struct domain *d, - * For this purpose (and to match populate_physmap() behavior), the page - * is kept allocated. - */ -- if ( !is_domain_direct_mapped(d) && -+ if ( !rc && !is_domain_direct_mapped(d) && - test_and_clear_bit(_PGC_allocated, &page->count_info) ) - put_page(page); - -- guest_physmap_remove_page(d, _gfn(gmfn), mfn, 0); -- - put_page(page); - put_gfn(d, gmfn); - -- return 0; -+ return rc; - } - - static void decrease_reservation(struct memop_args *a) -@@ -592,7 +596,8 @@ static long memory_exchange(XEN_GUEST_HA - gfn = mfn_to_gmfn(d, mfn); - /* Pages were unshared above */ - BUG_ON(SHARED_M2P(gfn)); -- guest_physmap_remove_page(d, _gfn(gfn), _mfn(mfn), 0); -+ if ( guest_physmap_remove_page(d, _gfn(gfn), _mfn(mfn), 0) ) -+ domain_crash(d); - put_page(page); - } - -@@ -1151,8 +1156,8 @@ long do_memory_op(unsigned long cmd, XEN - page = get_page_from_gfn(d, xrfp.gpfn, NULL, P2M_ALLOC); - if ( page ) - { -- guest_physmap_remove_page(d, _gfn(xrfp.gpfn), -- _mfn(page_to_mfn(page)), 0); -+ rc = guest_physmap_remove_page(d, _gfn(xrfp.gpfn), -+ _mfn(page_to_mfn(page)), 0); - put_page(page); - } - else ---- a/xen/drivers/passthrough/arm/smmu.c -+++ b/xen/drivers/passthrough/arm/smmu.c -@@ -2786,9 +2786,7 @@ static int __must_check arm_smmu_unmap_p - if ( !is_domain_direct_mapped(d) ) - return -EINVAL; - -- guest_physmap_remove_page(d, _gfn(gfn), _mfn(gfn), 0); -- -- return 0; -+ return guest_physmap_remove_page(d, _gfn(gfn), _mfn(gfn), 0); - } - - static const struct iommu_ops arm_smmu_iommu_ops = { ---- a/xen/include/asm-arm/p2m.h -+++ b/xen/include/asm-arm/p2m.h -@@ -268,10 +268,6 @@ static inline int guest_physmap_add_page - return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw); - } - --void guest_physmap_remove_page(struct domain *d, -- gfn_t gfn, -- mfn_t mfn, unsigned int page_order); -- - mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn); - - /* ---- a/xen/include/asm-x86/p2m.h -+++ b/xen/include/asm-x86/p2m.h -@@ -561,10 +561,6 @@ static inline int guest_physmap_add_page - return guest_physmap_add_entry(d, gfn, mfn, page_order, p2m_ram_rw); - } - --/* Remove a page from a domain's p2m table */ --int guest_physmap_remove_page(struct domain *d, -- gfn_t gfn, mfn_t mfn, unsigned int page_order); -- - /* Set a p2m range as populate-on-demand */ - int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn, - unsigned int order); ---- a/xen/include/xen/p2m-common.h -+++ b/xen/include/xen/p2m-common.h -@@ -1,6 +1,7 @@ - #ifndef _XEN_P2M_COMMON_H - #define _XEN_P2M_COMMON_H - -+#include <xen/mm.h> - #include <public/vm_event.h> - - /* -@@ -33,6 +34,11 @@ typedef enum { - /* NOTE: Assumed to be only 4 bits right now on x86. */ - } p2m_access_t; - -+/* Remove a page from a domain's p2m table */ -+int __must_check -+guest_physmap_remove_page(struct domain *d, gfn_t gfn, mfn_t mfn, -+ unsigned int page_order); -+ - /* Map MMIO regions in the p2m: start_gfn and nr describe the range in - * * the guest physical address space to map, starting from the machine - * * frame number mfn. */ ---- a/xen/include/xen/mm.h -+++ b/xen/include/xen/mm.h -@@ -554,7 +554,7 @@ int xenmem_add_to_physmap_one(struct dom - unsigned long idx, gfn_t gfn); - - /* Returns 0 on success, or negative on error. */ --int guest_remove_page(struct domain *d, unsigned long gmfn); -+int __must_check guest_remove_page(struct domain *d, unsigned long gmfn); - - #define RAM_TYPE_CONVENTIONAL 0x00000001 - #define RAM_TYPE_RESERVED 0x00000002 |