From e4a65bd4230abaae48d4f4b72f0c3028541c9c57 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 4 Jun 2026 21:42:55 +0100 Subject: [PATCH] domctl: handle XEN_DOMCTL_ioport_mapping without acquiring domctl lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 (cherry picked from commit 9ac94138a5f31b5325fe4401e5cd9e377bbedcdb) --- xen/arch/x86/domctl.c | 9 ++++++--- xen/common/domctl.c | 4 ++++ xen/include/xsm/dummy.h | 4 ++-- xen/xsm/flask/hooks.c | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index cb568bb1fe..12d8768da3 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -619,12 +619,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 diff --git a/xen/common/domctl.c b/xen/common/domctl.c index d2545569b7..0f3bb6087a 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -452,6 +452,10 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) 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; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index 7c45a330ae..60dc474b2b 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -167,12 +167,12 @@ static XSM_INLINE int cf_check xsm_domctl( 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_ioport_mapping: case XEN_DOMCTL_memory_mapping: ASSERT_UNREACHABLE(); return -EILSEQ; @@ -764,7 +764,7 @@ static XSM_INLINE int cf_check xsm_ioport_permission( 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); } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index a9d8140f10..bfdc5da2cd 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -680,6 +680,7 @@ static int cf_check flask_domctl(struct domain *d, unsigned int cmd, /* These have individual XSM hooks and don't make it here. */ case XEN_DOMCTL_getdomaininfo: + case XEN_DOMCTL_ioport_mapping: case XEN_DOMCTL_memory_mapping: ASSERT_UNREACHABLE(); return -EILSEQ; @@ -698,7 +699,6 @@ static int cf_check flask_domctl(struct domain *d, unsigned int cmd, /* These have individual XSM hooks (arch/x86/domctl.c) */ case XEN_DOMCTL_shadow_op: case XEN_DOMCTL_ioport_permission: - case XEN_DOMCTL_ioport_mapping: #endif #ifdef CONFIG_HAS_PASSTHROUGH /*