[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 2/2] xen/domain: rewrite emulation_flags_ok()
From: Denis Mukhin <dmukhin@xxxxxxxx> Rewrite emulation_flags_ok() to simplify future modifications. No functional change intended. Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx> Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> --- Changes since v3: - added R-b - fixed stray newline --- xen/arch/x86/domain.c | 91 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 0363ccb384..8d26887be2 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -743,32 +743,87 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) return 0; } +/* + * Verify that the domain's emulation flags resolve to a supported configuration. + * + * This ensures we only allow a known, safe subset of emulation combinations + * (for both functionality and security). Arbitrary mixes are likely to cause + * errors (e.g., null pointer dereferences). + * + * NB: use the internal X86_EMU_XXX symbols, not the public XEN_X86_EMU_XXX + * symbols. + */ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags) { + enum { + CAP_PV = BIT(0, U), + CAP_HVM = BIT(1, U), + CAP_HWDOM = BIT(2, U), + CAP_DOMU = BIT(3, U), + }; + static const struct { + unsigned int caps; + uint32_t min; + uint32_t opt; + } configs[] = { +#ifdef CONFIG_PV + /* PV */ + { + .caps = CAP_PV | CAP_DOMU, + .min = 0, + .opt = 0, + }, + + /* PV (likely dom0) */ + { + .caps = CAP_PV | CAP_HWDOM, + .min = X86_EMU_PIT, + .opt = 0, + }, +#endif /* #ifdef CONFIG_PV */ + +#ifdef CONFIG_HVM + /* PVH dom0/domU or HVM domU */ + { + .caps = CAP_HVM | CAP_HWDOM, + .min = X86_EMU_LAPIC | X86_EMU_IOAPIC | X86_EMU_VPCI, + .opt = 0, + }, + + /* HVM domU */ + { + .caps = CAP_HVM | CAP_DOMU, + .min = X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ), + /* HVM PIRQ feature is user-selectable. */ + .opt = X86_EMU_USE_PIRQ, + }, + + /* PVH */ + { + .caps = CAP_HVM | CAP_DOMU, + .min = X86_EMU_LAPIC, + .opt = 0, + }, +#endif /* #ifdef CONFIG_HVM */ + }; + unsigned int i, caps = is_hardware_domain(d) ? CAP_HWDOM : CAP_DOMU; + + if ( is_pv_domain(d) ) + caps |= CAP_PV; + else if ( is_hvm_domain(d) ) + caps |= CAP_HVM; + #ifdef CONFIG_HVM /* This doesn't catch !CONFIG_HVM case but it is better than nothing */ BUILD_BUG_ON(X86_EMU_ALL != XEN_X86_EMU_ALL); #endif - if ( is_hvm_domain(d) ) - { - if ( is_hardware_domain(d) && - emflags != (X86_EMU_VPCI | X86_EMU_LAPIC | X86_EMU_IOAPIC) ) - return false; - if ( !is_hardware_domain(d) && - /* HVM PIRQ feature is user-selectable. */ - (emflags & ~X86_EMU_USE_PIRQ) != - (X86_EMU_ALL & ~(X86_EMU_VPCI | X86_EMU_USE_PIRQ)) && - emflags != X86_EMU_LAPIC ) - return false; - } - else if ( emflags != 0 && emflags != X86_EMU_PIT ) - { - /* PV or classic PVH. */ - return false; - } + for ( i = 0; i < ARRAY_SIZE(configs); i++ ) + if ( caps == configs[i].caps && + (emflags & ~configs[i].opt) == configs[i].min ) + return true; - return true; + return false; } void __init arch_init_idle_domain(struct domain *d) -- 2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |