From: Jan Beulich Subject: domctl: handle XEN_DOMCTL_ioport_mapping without acquiring domctl lock With dedicated locking added, the domctl lock isn't required here anymore. As the handling is in arch-specific code (x86 only), almost no code is being moved, but a 2nd (extensible to other sub-ops) invocation of arch_do_domctl() is being added. Move just the re-purposed dedicated XSM check as early as possible. In flask_domctl() don't put #ifdef around the moved case label. This is part of XSA-492. Fixes: fda49f9b3fbb ("Add build option to allow more hypercalls from stubdoms") Reported-by: Andrew Cooper Signed-off-by: Jan Beulich Reviewed-by: Roger Pau Monné Acked-by: Daniel P. Smith --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -667,12 +667,15 @@ long arch_do_domctl( break; } + ret = xsm_ioport_mapping(XSM_DM_PRIV, d, fmp, fmp + np - 1, add); + if ( ret ) + break; + hvm = &d->arch.hvm; iocaps_double_lock(d, true); - if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) || - (ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add)) ) - ret = ret ?: -EPERM; + if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) ) + ret = -EPERM; else if ( add ) { printk(XENLOG_G_INFO --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -436,6 +436,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xe goto domctl_out_unlock_domonly; } + case XEN_DOMCTL_ioport_mapping: + ret = arch_do_domctl(op, d, u_domctl); + goto domctl_out_unlock_domonly; + default: /* Everything else handled further down. */ break; --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -167,13 +167,13 @@ static XSM_INLINE int cf_check xsm_domct XSM_ASSERT_ACTION(XSM_OTHER); switch ( cmd ) { - case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_bind_pt_irq: case XEN_DOMCTL_unbind_pt_irq: return xsm_default_action(XSM_DM_PRIV, current->domain, d); case XEN_DOMCTL_getdomaininfo: case XEN_DOMCTL_get_domain_state: + case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_memory_mapping: ASSERT_UNREACHABLE(); return -EILSEQ; @@ -765,7 +765,7 @@ static XSM_INLINE int cf_check xsm_iopor static XSM_INLINE int cf_check xsm_ioport_mapping( XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow) { - XSM_ASSERT_ACTION(XSM_HOOK); + XSM_ASSERT_ACTION(XSM_DM_PRIV); return xsm_default_action(action, current->domain, d); } --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -652,6 +652,7 @@ static int cf_check flask_domctl(struct /* These have individual XSM hooks and don't make it here. */ case XEN_DOMCTL_getdomaininfo: case XEN_DOMCTL_get_domain_state: + case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_memory_mapping: ASSERT_UNREACHABLE(); return -EILSEQ; @@ -670,7 +671,6 @@ static int cf_check flask_domctl(struct /* These have individual XSM hooks (arch/x86/domctl.c) */ case XEN_DOMCTL_shadow_op: case XEN_DOMCTL_ioport_permission: - case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_gsi_permission: #endif #ifdef CONFIG_HAS_PASSTHROUGH