diff options
Diffstat (limited to '0004-x86-p2m-add-option-to-skip-root-pagetable-removal-in.patch')
-rw-r--r-- | 0004-x86-p2m-add-option-to-skip-root-pagetable-removal-in.patch | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/0004-x86-p2m-add-option-to-skip-root-pagetable-removal-in.patch b/0004-x86-p2m-add-option-to-skip-root-pagetable-removal-in.patch new file mode 100644 index 0000000..b3edbd9 --- /dev/null +++ b/0004-x86-p2m-add-option-to-skip-root-pagetable-removal-in.patch @@ -0,0 +1,138 @@ +From 8fc19c143b8aa563077f3d5c46fcc0a54dc04f35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= <roger.pau@citrix.com> +Date: Tue, 11 Oct 2022 14:52:39 +0200 +Subject: [PATCH 04/26] x86/p2m: add option to skip root pagetable removal in + p2m_teardown() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a new parameter to p2m_teardown() in order to select whether the +root page table should also be freed. Note that all users are +adjusted to pass the parameter to remove the root page tables, so +behavior is not modified. + +No functional change intended. + +This is part of CVE-2022-33746 / XSA-410. + +Suggested-by: Julien Grall <julien@xen.org> +Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> +Acked-by: Tim Deegan <tim@xen.org> +master commit: 1df52a270225527ae27bfa2fc40347bf93b78357 +master date: 2022-10-11 14:21:23 +0200 +--- + xen/arch/x86/mm/hap/hap.c | 6 +++--- + xen/arch/x86/mm/p2m.c | 20 ++++++++++++++++---- + xen/arch/x86/mm/shadow/common.c | 4 ++-- + xen/include/asm-x86/p2m.h | 2 +- + 4 files changed, 22 insertions(+), 10 deletions(-) + +diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c +index 47a7487fa7a3..a8f5a19da917 100644 +--- a/xen/arch/x86/mm/hap/hap.c ++++ b/xen/arch/x86/mm/hap/hap.c +@@ -541,18 +541,18 @@ void hap_final_teardown(struct domain *d) + } + + for ( i = 0; i < MAX_ALTP2M; i++ ) +- p2m_teardown(d->arch.altp2m_p2m[i]); ++ p2m_teardown(d->arch.altp2m_p2m[i], true); + } + + /* Destroy nestedp2m's first */ + for (i = 0; i < MAX_NESTEDP2M; i++) { +- p2m_teardown(d->arch.nested_p2m[i]); ++ p2m_teardown(d->arch.nested_p2m[i], true); + } + + if ( d->arch.paging.hap.total_pages != 0 ) + hap_teardown(d, NULL); + +- p2m_teardown(p2m_get_hostp2m(d)); ++ p2m_teardown(p2m_get_hostp2m(d), true); + /* Free any memory that the p2m teardown released */ + paging_lock(d); + hap_set_allocation(d, 0, NULL); +diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c +index def1695cf00b..aba4f17cbe12 100644 +--- a/xen/arch/x86/mm/p2m.c ++++ b/xen/arch/x86/mm/p2m.c +@@ -749,11 +749,11 @@ int p2m_alloc_table(struct p2m_domain *p2m) + * hvm fixme: when adding support for pvh non-hardware domains, this path must + * cleanup any foreign p2m types (release refcnts on them). + */ +-void p2m_teardown(struct p2m_domain *p2m) ++void p2m_teardown(struct p2m_domain *p2m, bool remove_root) + /* Return all the p2m pages to Xen. + * We know we don't have any extra mappings to these pages */ + { +- struct page_info *pg; ++ struct page_info *pg, *root_pg = NULL; + struct domain *d; + + if (p2m == NULL) +@@ -763,10 +763,22 @@ void p2m_teardown(struct p2m_domain *p2m) + + p2m_lock(p2m); + ASSERT(atomic_read(&d->shr_pages) == 0); +- p2m->phys_table = pagetable_null(); ++ ++ if ( remove_root ) ++ p2m->phys_table = pagetable_null(); ++ else if ( !pagetable_is_null(p2m->phys_table) ) ++ { ++ root_pg = pagetable_get_page(p2m->phys_table); ++ clear_domain_page(pagetable_get_mfn(p2m->phys_table)); ++ } + + while ( (pg = page_list_remove_head(&p2m->pages)) ) +- d->arch.paging.free_page(d, pg); ++ if ( pg != root_pg ) ++ d->arch.paging.free_page(d, pg); ++ ++ if ( root_pg ) ++ page_list_add(root_pg, &p2m->pages); ++ + p2m_unlock(p2m); + } + +diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c +index 8c1b041f7135..8c5baba9544d 100644 +--- a/xen/arch/x86/mm/shadow/common.c ++++ b/xen/arch/x86/mm/shadow/common.c +@@ -2701,7 +2701,7 @@ int shadow_enable(struct domain *d, u32 mode) + paging_unlock(d); + out_unlocked: + if ( rv != 0 && !pagetable_is_null(p2m_get_pagetable(p2m)) ) +- p2m_teardown(p2m); ++ p2m_teardown(p2m, true); + if ( rv != 0 && pg != NULL ) + { + pg->count_info &= ~PGC_count_mask; +@@ -2866,7 +2866,7 @@ void shadow_final_teardown(struct domain *d) + shadow_teardown(d, NULL); + + /* It is now safe to pull down the p2m map. */ +- p2m_teardown(p2m_get_hostp2m(d)); ++ p2m_teardown(p2m_get_hostp2m(d), true); + /* Free any shadow memory that the p2m teardown released */ + paging_lock(d); + shadow_set_allocation(d, 0, NULL); +diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h +index f2af7a746ced..c3c16748e7d5 100644 +--- a/xen/include/asm-x86/p2m.h ++++ b/xen/include/asm-x86/p2m.h +@@ -574,7 +574,7 @@ int p2m_init(struct domain *d); + int p2m_alloc_table(struct p2m_domain *p2m); + + /* Return all the p2m resources to Xen. */ +-void p2m_teardown(struct p2m_domain *p2m); ++void p2m_teardown(struct p2m_domain *p2m, bool remove_root); + void p2m_final_teardown(struct domain *d); + + /* Add a page to a domain's p2m table */ +-- +2.37.3 + |