From 628cd49525fa0889d68ed4c9cec22bf81846329f Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 20 Jul 2026 16:42:22 +0100 Subject: [PATCH] sysctl/XSM: drop .resource_{,un}plug_core() hooks Integrate the checking with xsm_sysctl(), now that it has the full op struct passed. As a positive side effect, permissions are then checked at the same early point with and without Flask. Note that these were x86- only, i.e. some dead/unreachable code gets eliminated for (in particular) Arm. This is part of CVE-2026-62426 / XSA-499. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Acked-By: Daniel P. Smith (cherry picked from commit 0501e1dc047768cba2a458b25f5e9214726c33c8) --- xen/arch/x86/sysctl.c | 10 +--------- xen/include/xsm/dummy.h | 12 ------------ xen/include/xsm/xsm.h | 12 ------------ xen/xsm/dummy.c | 2 -- xen/xsm/flask/hooks.c | 29 ++++++++++++++++++++++------- 5 files changed, 23 insertions(+), 42 deletions(-) diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 1d40d82c5a..1db996760e 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -117,20 +117,17 @@ long arch_do_sysctl( { unsigned int cpu = sysctl->u.cpu_hotplug.cpu; unsigned int op = sysctl->u.cpu_hotplug.op; - bool plug; long (*fn)(void *data); void *hcpu; switch ( op ) { case XEN_SYSCTL_CPU_HOTPLUG_ONLINE: - plug = true; fn = cpu_up_helper; hcpu = _p(cpu); break; case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE: - plug = false; fn = cpu_down_helper; hcpu = _p(cpu); break; @@ -150,9 +147,8 @@ long arch_do_sysctl( if ( CONFIG_NR_CPUS <= 1 ) /* Mimic behavior of smt_up_down_helper(). */ return 0; - plug = op == XEN_SYSCTL_CPU_HOTPLUG_SMT_ENABLE; fn = smt_up_down_helper; - hcpu = _p(plug); + hcpu = _p(op == XEN_SYSCTL_CPU_HOTPLUG_SMT_ENABLE); break; default: @@ -160,10 +156,6 @@ long arch_do_sysctl( break; } - if ( !ret ) - ret = plug ? xsm_resource_plug_core(XSM_HOOK) - : xsm_resource_unplug_core(XSM_HOOK); - if ( !ret ) ret = continue_hypercall_on_cpu(0, fn, hcpu); } diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index b3969c4f32..2dc41d7307 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -395,18 +395,6 @@ static XSM_INLINE int cf_check xsm_get_device_group( } #endif /* HAS_PASSTHROUGH && HAS_PCI */ -static XSM_INLINE int cf_check xsm_resource_plug_core(XSM_DEFAULT_VOID) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, NULL); -} - -static XSM_INLINE int cf_check xsm_resource_unplug_core(XSM_DEFAULT_VOID) -{ - XSM_ASSERT_ACTION(XSM_HOOK); - return xsm_default_action(action, current->domain, NULL); -} - static XSM_INLINE int cf_check xsm_resource_plug_pci( XSM_DEFAULT_ARG uint32_t machine_bdf) { diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 87e277aa38..b5d4e9fe43 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -123,8 +123,6 @@ struct xsm_ops { int (*get_device_group)(uint32_t machine_bdf); #endif - int (*resource_plug_core)(void); - int (*resource_unplug_core)(void); int (*resource_plug_pci)(uint32_t machine_bdf); int (*resource_unplug_pci)(uint32_t machine_bdf); int (*resource_setup_pci)(uint32_t machine_bdf); @@ -508,16 +506,6 @@ static inline int xsm_resource_unplug_pci( return alternative_call(xsm_ops.resource_unplug_pci, machine_bdf); } -static inline int xsm_resource_plug_core(xsm_default_t def) -{ - return alternative_call(xsm_ops.resource_plug_core); -} - -static inline int xsm_resource_unplug_core(xsm_default_t def) -{ - return alternative_call(xsm_ops.resource_unplug_core); -} - static inline int xsm_resource_setup_pci( xsm_default_t def, uint32_t machine_bdf) { diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 97c06ee522..bb38d6023d 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -77,8 +77,6 @@ static const struct xsm_ops __initconst_cf_clobber dummy_ops = { .get_device_group = xsm_get_device_group, #endif - .resource_plug_core = xsm_resource_plug_core, - .resource_unplug_core = xsm_resource_unplug_core, .resource_plug_pci = xsm_resource_plug_pci, .resource_unplug_pci = xsm_resource_unplug_pci, .resource_setup_pci = xsm_resource_setup_pci, diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 1704b7ae8a..188187bd16 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -56,6 +56,9 @@ static int flask_deassign_dtdevice(struct domain *d, const char *dtpath); #endif #endif /* CONFIG_HAS_PASSTHROUGH */ +static int flask_resource_plug_core(void); +static int flask_resource_unplug_core(void); + static uint32_t domain_sid(const struct domain *dom) { struct domain_security_struct *dsec = dom->ssid; @@ -901,9 +904,6 @@ static int cf_check flask_sysctl(const struct xen_sysctl *op) { /* These have individual XSM hooks */ case XEN_SYSCTL_page_offline_op: -#ifdef CONFIG_X86 - case XEN_SYSCTL_cpu_hotplug: -#endif return 0; case XEN_SYSCTL_readconsole: @@ -955,6 +955,23 @@ static int cf_check flask_sysctl(const struct xen_sysctl *op) case XEN_SYSCTL_getdomaininfolist: return flask_getdomaininfo(dom_xen); +#ifdef CONFIG_X86 + case XEN_SYSCTL_cpu_hotplug: + switch ( op->u.cpu_hotplug.op ) + { + case XEN_SYSCTL_CPU_HOTPLUG_ONLINE: + case XEN_SYSCTL_CPU_HOTPLUG_SMT_ENABLE: + return flask_resource_plug_core(); + + case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE: + case XEN_SYSCTL_CPU_HOTPLUG_SMT_DISABLE: + return flask_resource_unplug_core(); + + default: + return avc_unknown_permission("cpu_hotplug", op->u.cpu_hotplug.op); + } +#endif + case XEN_SYSCTL_psr_cmt_op: return avc_current_has_perm(SECINITSID_XEN, SECCLASS_XEN2, XEN2__PSR_CMT_OP, NULL); @@ -1232,12 +1249,12 @@ static int cf_check flask_pci_config_permission( } -static int cf_check flask_resource_plug_core(void) +static int flask_resource_plug_core(void) { return avc_current_has_perm(SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__PLUG, NULL); } -static int cf_check flask_resource_unplug_core(void) +static int flask_resource_unplug_core(void) { return avc_current_has_perm(SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__UNPLUG, NULL); } @@ -1958,8 +1975,6 @@ static const struct xsm_ops __initconst_cf_clobber flask_ops = { .iomem_mapping_vpci = flask_iomem_mapping, .pci_config_permission = flask_pci_config_permission, - .resource_plug_core = flask_resource_plug_core, - .resource_unplug_core = flask_resource_unplug_core, .resource_plug_pci = flask_resource_plug_pci, .resource_unplug_pci = flask_resource_unplug_pci, .resource_setup_pci = flask_resource_setup_pci,