|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v5 02/45] x86/mm: refuse to promote an L4 while the domain has no per-domain L3
init_xen_l4_slots() puts the domain's per-domain L3 in slot 260 of the
L4s it fills. Since fcf91ce9de66 ("x86/pv: don't populate the GDT/LDT
L3 slot at domain creation") a PV domain gets that L3 with its first
vCPU (pv_create_gdt_ldt_l1tab()). Only mapcache_domain_init() makes it
earlier, with the domain, and release builds skip that unless memory
hotplug is enabled or the host's memory reaches past the part of the
directmap PV guests can see. So in release builds on most hosts, an L4
that is promoted before XEN_DOMCTL_max_vcpus has created the domain's
vCPUs gets a slot 260 entry made from a NULL page (0x803e900000000063),
pointing far beyond the host's memory.
Have promote_l4_table() return -EINVAL while the domain has no
per-domain L3, before taking any reference. The other callers of
init_xen_l4_slots() all run once the L3 exists; have init_xen_l4_slots()
check that with a BUG_ON(). An ASSERT() would not do: the case above
arises only in release builds. libxl is unaffected: it creates the
vCPUs before it builds or restores a domain.
There's no way to trigger the issue from the current toolstack; this
is just belt-and-braces.
Fixes: fcf91ce9de66 ("x86/pv: don't populate the GDT/LDT L3 slot at domain
creation")
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>
---
Changes in v5:
- Test for the per-domain L3 itself, not for vCPU 0 (Roger).
- BUG_ON() in init_xen_l4_slots() if the domain has no per-domain L3.
- Retitle (was: "x86/mm: refuse to promote an L4 while the domain has
no vCPU").
Changes in v4:
- New in this version, split out of "x86/hvm: introduce per-vCPU L3
page-table": promote_l4_table() fails while the domain has no vCPU
---
xen/arch/x86/mm.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index e42cd33c0d..f00f0b831d 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1721,6 +1721,7 @@ void init_xen_l4_slots(l4_pgentry_t *l4t, mfn_t l4mfn,
l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR_RW);
/* Slot 260: Per-domain mappings. */
+ BUG_ON(!d->arch.perdomain_l3_pg);
l4t[l4_table_offset(PERDOMAIN_VIRT_START)] =
l4e_from_page(d->arch.perdomain_l3_pg, __PAGE_HYPERVISOR_RW);
@@ -1798,11 +1799,20 @@ static int promote_l4_table(struct page_info *page)
{
struct domain *d = page_get_owner(page);
mfn_t l4mfn = page_to_mfn(page);
- l4_pgentry_t *pl4e = map_domain_page(l4mfn);
+ l4_pgentry_t *pl4e;
unsigned int i;
int rc = 0;
unsigned int partial_flags = page->partial_flags;
+ /*
+ * init_xen_l4_slots() puts the domain's per-domain L3 in slot 260, and a
+ * PV domain may get that only with its first vCPU.
+ */
+ if ( !d->arch.perdomain_l3_pg )
+ return -EINVAL;
+
+ pl4e = map_domain_page(l4mfn);
+
for ( i = page->nr_validated_ptes; i < L4_PAGETABLE_ENTRIES;
i++, partial_flags = 0 )
{
--
2.56.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |