* [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499
@ 2026-08-17 8:49 Jan Beulich
2026-08-17 8:51 ` [PATCH v2 01/14] XSM: make xsm_default_action() const-correct Jan Beulich
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:49 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org; +Cc: Daniel Smith
Working on those XSAs made pretty apparent that there's a lot of redundancy,
requiring changes in too many separate places if e.g. adding / altering /
removing a hook. Obviously while dealing with that, some other, smaller
tidying opportunities turned up as well, which is what is being dealt with
here.
v2 addresses review feedback and includes a few new patches. See individual
patches for details.
01: XSM: make xsm_default_action() const-correct
02: XSM: convert "allow" (Flask: "access") parameters to bool
03: x86/mm: get_page_from_l1e() is PV-or-shadow-only
04: x86: restrict PHYSDEVOP_* when PV=n
05: XSM: make Argo hooks well-formed ones
06: XSM: fold xsm_{,un}map_domain_pirq() hooks
07: x86: type-correct last parameter of map_domain_pirq()
08: XSM: pass just SBDF to xsm_{,un}map_domain_irq()
09: XSM: fold xsm_{,un}map_domain_irq() hooks
10: XSM: fold xsm_{,un}bind_pt_irq() hooks
11: XSM: convert remaining event channel hooks
12: XSM: convert remaining domain-related hooks
13: XSM: convert remaining miscellaneous hooks
14: XSM: avoid fragile assumptions in xsm_fixup_ops()
Jan
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 01/14] XSM: make xsm_default_action() const-correct
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
@ 2026-08-17 8:51 ` Jan Beulich
2026-08-17 8:51 ` [PATCH v2 02/14] XSM: convert "allow" (Flask: "access") parameters to bool Jan Beulich
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:51 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Frediano Ziglio, Jason Andryuk
To be able to properly use const on dummy hook function parameters, add
const to both domain pointers.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
---
v2: Split off from Argo patch.
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -76,7 +76,7 @@ void __xsm_action_mismatch_detected(void
#endif /* CONFIG_XSM */
static always_inline int xsm_default_action(
- xsm_default_t action, struct domain *src, struct domain *target)
+ xsm_default_t action, const struct domain *src, const struct domain *target)
{
switch ( action ) {
case XSM_HOOK:
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 02/14] XSM: convert "allow" (Flask: "access") parameters to bool
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
2026-08-17 8:51 ` [PATCH v2 01/14] XSM: make xsm_default_action() const-correct Jan Beulich
@ 2026-08-17 8:51 ` Jan Beulich
2026-08-17 8:52 ` [PATCH v2 03/14] x86/mm: get_page_from_l1e() is PV-or-shadow-only Jan Beulich
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:51 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Teddy Astie, Roger Pau Monné
These are boolean, so they should always have used bool (originally
bool_t), not uint8_t. Leverage recent changes to arrange for this with
(now) fewer places which need changing (within the XSM machinery itself).
Adjust call sites as well, where the conversion wasn't done so far.
While doing this, rename flask_io{port,mem}_mapping()'s last parameters to
"map".
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
Why is it that Arm doesn't use xsm_irq_permission() at all? Same for Arm64
vs xsm_pci_config_permission().
---
v2: Rename flask_io{port,mem}_mapping()'s last parameters to "map".
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -235,7 +235,7 @@ long arch_do_domctl(
{
unsigned int fp = domctl->u.ioport_permission.first_port;
unsigned int np = domctl->u.ioport_permission.nr_ports;
- int allow = domctl->u.ioport_permission.allow_access;
+ bool allow = domctl->u.ioport_permission.allow_access;
ret = -EINVAL;
if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
@@ -306,7 +306,8 @@ long arch_do_domctl(
break;
}
- ret = xsm_irq_permission(XSM_PRIV, d, irq, flags);
+ ret = xsm_irq_permission(XSM_PRIV, d, irq,
+ flags & XEN_DOMCTL_GSI_ACTION_MASK);
if ( ret )
break;
@@ -687,7 +688,7 @@ long arch_do_domctl(
unsigned int fgp = domctl->u.ioport_mapping.first_gport;
unsigned int fmp = domctl->u.ioport_mapping.first_mport;
unsigned int np = domctl->u.ioport_mapping.nr_ports;
- unsigned int add = domctl->u.ioport_mapping.add_mapping;
+ bool add = domctl->u.ioport_mapping.add_mapping;
struct hvm_domain *hvm;
struct g2m_ioport *g2m_ioport;
int found = 0;
--- a/xen/arch/x86/pci.c
+++ b/xen/arch/x86/pci.c
@@ -78,7 +78,7 @@ int pci_conf_write_intercept(unsigned in
{
struct pci_dev *pdev;
int rc = xsm_pci_config_permission(XSM_HOOK, current->domain, bdf,
- reg, reg + size - 1, 1);
+ reg, reg + size - 1, true);
if ( rc < 0 )
return rc;
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -260,7 +260,7 @@ static bool pci_cfg_ok(struct domain *cu
return !write ?
xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,
- start, start + size - 1, 0) == 0 :
+ start, start + size - 1, false) == 0 :
pci_conf_write_intercept(0, machine_bdf, start, size, write) >= 0;
}
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -505,21 +505,21 @@ static XSM_INLINE int xsm_unmap_domain_i
}
static XSM_INLINE int xsm_irq_permission(
- XSM_DEFAULT_ARG struct domain *d, int pirq, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, int pirq, bool allow)
{
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
static XSM_INLINE int xsm_iomem_permission(
- XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, bool allow)
{
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
static XSM_INLINE int xsm_iomem_mapping(
- XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, bool allow)
{
XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
@@ -527,7 +527,7 @@ static XSM_INLINE int xsm_iomem_mapping(
#ifdef CONFIG_HAS_VPCI
static XSM_INLINE int xsm_iomem_mapping_vpci(
- XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, bool allow)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
@@ -537,7 +537,7 @@ static XSM_INLINE int xsm_iomem_mapping_
#ifdef CONFIG_HAS_PCI
static XSM_INLINE int xsm_pci_config_permission(
XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf, uint16_t start,
- uint16_t end, uint8_t access)
+ uint16_t end, bool access)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
@@ -709,14 +709,14 @@ static XSM_INLINE int xsm_priv_mapping(
}
static XSM_INLINE int xsm_ioport_permission(
- XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, bool allow)
{
XSM_ASSERT_ACTION(XSM_PRIV);
return xsm_default_action(action, current->domain, d);
}
static XSM_INLINE int xsm_ioport_mapping(
- XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+ XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, bool allow)
{
XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -77,12 +77,12 @@ XSM_HOOK(int, unmap_domain_irq, struct d
XSM_HOOK(int, bind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
XSM_HOOK(int, unbind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
-XSM_HOOK(int, irq_permission, struct domain *, int, uint8_t)
-XSM_HOOK(int, iomem_permission, struct domain *, uint64_t, uint64_t, uint8_t)
+XSM_HOOK(int, irq_permission, struct domain *, int, bool)
+XSM_HOOK(int, iomem_permission, struct domain *, uint64_t, uint64_t, bool)
-XSM_HOOK(int, iomem_mapping, struct domain *, uint64_t, uint64_t, uint8_t)
+XSM_HOOK(int, iomem_mapping, struct domain *, uint64_t, uint64_t, bool)
#ifdef CONFIG_HAS_VPCI
-XSM_HOOK(int, iomem_mapping_vpci, struct domain *, uint64_t, uint64_t, uint8_t)
+XSM_HOOK(int, iomem_mapping_vpci, struct domain *, uint64_t, uint64_t, bool)
#endif
#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
@@ -97,7 +97,7 @@ XSM_HOOK(int, resource_setup_misc)
XSM_HOOK(int, resource_setup_pci, uint32_t)
XSM_HOOK(int, resource_setup_gsi, int)
XSM_HOOK(int, pci_config_permission, struct domain *, uint32_t, uint16_t,
- uint16_t, uint8_t)
+ uint16_t, bool)
#endif
#ifdef CONFIG_HYPFS
@@ -142,8 +142,8 @@ XSM_HOOK(int, mmuext_op, struct domain *
XSM_HOOK(int, update_va_mapping, struct domain *, struct domain *, l1_pgentry_t)
#endif /* CONFIG_PV */
XSM_HOOK(int, priv_mapping, struct domain *, struct domain *)
-XSM_HOOK(int, ioport_permission, struct domain *, uint32_t, uint32_t, uint8_t)
-XSM_HOOK(int, ioport_mapping, struct domain *, uint32_t, uint32_t, uint8_t)
+XSM_HOOK(int, ioport_permission, struct domain *, uint32_t, uint32_t, bool)
+XSM_HOOK(int, ioport_mapping, struct domain *, uint32_t, uint32_t, bool)
XSM_HOOK(int, pmu_op, struct domain *, unsigned int)
#endif /* CONFIG_X86 */
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -998,7 +998,7 @@ static int cf_check flask_sysctl(const s
}
#endif /* CONFIG_SYSCTL */
-static inline uint32_t resource_to_perm(uint8_t access)
+static inline uint32_t resource_to_perm(bool access)
{
if ( access )
return RESOURCE__ADD;
@@ -1166,7 +1166,7 @@ static int cf_check flask_unbind_pt_irq(
}
static int cf_check flask_irq_permission(
- struct domain *d, int pirq, uint8_t access)
+ struct domain *d, int pirq, bool access)
{
/* the PIRQ number is not useful; real IRQ is checked during mapping */
return current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(access));
@@ -1199,7 +1199,7 @@ static int cf_check _iomem_has_perm(
}
static int cf_check flask_iomem_permission(
- struct domain *d, uint64_t start, uint64_t end, uint8_t access)
+ struct domain *d, uint64_t start, uint64_t end, bool access)
{
struct iomem_has_perm_data data;
int rc;
@@ -1221,16 +1221,17 @@ static int cf_check flask_iomem_permissi
return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data);
}
-static int cf_check flask_iomem_mapping(struct domain *d, uint64_t start, uint64_t end, uint8_t access)
+static int cf_check flask_iomem_mapping(
+ struct domain *d, uint64_t start, uint64_t end, bool map)
{
- return flask_iomem_permission(d, start, end, access);
+ return flask_iomem_permission(d, start, end, map);
}
#define flask_iomem_mapping_vpci flask_iomem_mapping
#ifdef CONFIG_HAS_PCI
static int cf_check flask_pci_config_permission(
struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end,
- uint8_t access)
+ bool access)
{
uint32_t dsid, rsid;
int rc = -EPERM;
@@ -1709,7 +1710,7 @@ static int cf_check _ioport_has_perm(
}
static int cf_check flask_ioport_permission(
- struct domain *d, uint32_t start, uint32_t end, uint8_t access)
+ struct domain *d, uint32_t start, uint32_t end, bool access)
{
int rc;
struct ioport_has_perm_data data;
@@ -1733,9 +1734,9 @@ static int cf_check flask_ioport_permiss
}
static int cf_check flask_ioport_mapping(
- struct domain *d, uint32_t start, uint32_t end, uint8_t access)
+ struct domain *d, uint32_t start, uint32_t end, bool map)
{
- return flask_ioport_permission(d, start, end, access);
+ return flask_ioport_permission(d, start, end, map);
}
#ifdef CONFIG_MEM_SHARING
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 03/14] x86/mm: get_page_from_l1e() is PV-or-shadow-only
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
2026-08-17 8:51 ` [PATCH v2 01/14] XSM: make xsm_default_action() const-correct Jan Beulich
2026-08-17 8:51 ` [PATCH v2 02/14] XSM: convert "allow" (Flask: "access") parameters to bool Jan Beulich
@ 2026-08-17 8:52 ` Jan Beulich
2026-08-17 8:52 ` [PATCH v2 04/14] x86: restrict PHYSDEVOP_* when PV=n Jan Beulich
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:52 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Teddy Astie, Roger Pau Monné
Otherwise the function is unreachable, violating MISRA C:2012 rule 2.1.
With the function compiled out, its dedicated XSM hook also becomes
unreachable, so it is similarly guarded.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
It feels suspicious that the .priv_mapping() check is used for HVM guests
in shadow mode, but not for ones in HAP mode.
---
v2: Also conditionalize the declaration.
--- a/xen/arch/x86/include/asm/mm.h
+++ b/xen/arch/x86/include/asm/mm.h
@@ -404,10 +404,13 @@ int get_page_type(struct page_info *pag
int put_page_type_preemptible(struct page_info *page);
int get_page_type_preemptible(struct page_info *page, unsigned long type);
int put_old_guest_table(struct vcpu *v);
-int get_page_from_l1e(
- l1_pgentry_t l1e, struct domain *l1e_owner, struct domain *pg_owner);
void put_page_from_l1e(l1_pgentry_t l1e, struct domain *l1e_owner);
+#if defined(CONFIG_PV) || defined(CONFIG_SHADOW_PAGING)
+int get_page_from_l1e(
+ l1_pgentry_t l1e, struct domain *l1e_owner, struct domain *pg_owner);
+#endif
+
static inline struct page_info *get_page_from_mfn(mfn_t mfn, struct domain *d)
{
struct page_info *page = mfn_to_page(mfn);
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -836,6 +836,8 @@ static int cf_check print_mmio_emul_rang
}
#endif
+#if defined(CONFIG_PV) || defined(CONFIG_SHADOW_PAGING)
+
/*
* get_page_from_l1e returns:
* 0 => success (page not present also counts as such)
@@ -1037,6 +1039,8 @@ get_page_from_l1e(
return -EBUSY;
}
+#endif /* CONFIG_PV || CONFIG_SHADOW_PAGING */
+
/*
* The following flags are used to specify behavior of various get and
* put commands. The first is also stored in page->partial_flags to
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -701,12 +701,14 @@ static XSM_INLINE int xsm_update_va_mapp
#endif /* CONFIG_PV */
+#if defined(CONFIG_PV) || defined(CONFIG_SHADOW_PAGING)
static XSM_INLINE int xsm_priv_mapping(
XSM_DEFAULT_ARG struct domain *d, struct domain *t)
{
XSM_ASSERT_ACTION(XSM_TARGET);
return xsm_default_action(action, d, t);
}
+#endif
static XSM_INLINE int xsm_ioport_permission(
XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, bool allow)
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -141,7 +141,9 @@ XSM_HOOK(int, mmu_update, struct domain
XSM_HOOK(int, mmuext_op, struct domain *, struct domain *)
XSM_HOOK(int, update_va_mapping, struct domain *, struct domain *, l1_pgentry_t)
#endif /* CONFIG_PV */
+#if defined(CONFIG_PV) || defined(CONFIG_SHADOW_PAGING)
XSM_HOOK(int, priv_mapping, struct domain *, struct domain *)
+#endif
XSM_HOOK(int, ioport_permission, struct domain *, uint32_t, uint32_t, bool)
XSM_HOOK(int, ioport_mapping, struct domain *, uint32_t, uint32_t, bool)
XSM_HOOK(int, pmu_op, struct domain *, unsigned int)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1829,10 +1829,12 @@ static int cf_check flask_update_va_mapp
#endif /* CONFIG_PV */
+#if defined(CONFIG_PV) || defined(CONFIG_SHADOW_PAGING)
static int cf_check flask_priv_mapping(struct domain *d, struct domain *t)
{
return domain_has_perm(d, t, SECCLASS_MMU, MMU__TARGET_HACK);
}
+#endif
static int cf_check flask_pmu_op(struct domain *d, unsigned int op)
{
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 04/14] x86: restrict PHYSDEVOP_* when PV=n
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (2 preceding siblings ...)
2026-08-17 8:52 ` [PATCH v2 03/14] x86/mm: get_page_from_l1e() is PV-or-shadow-only Jan Beulich
@ 2026-08-17 8:52 ` Jan Beulich
2026-08-17 8:53 ` [PATCH v2 05/14] XSM: make Argo hooks well-formed ones Jan Beulich
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:52 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org; +Cc: Daniel Smith
hvm_physdev_op() permits through only a subset of sub-ops. The code
handling other sub-ops is therefore unreachable when PV=n, violating MISRA
C:2012 rule 2.1. With that the XSM .apic() hook also becomes unreachable /
dead when PV=n.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
At least for the sub-ops using xsm_apic() IS_ENABLED() cannot be used.
Therefore #ifdef is used throughout.
---
v2: Re-base over re-ordering of series.
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -233,6 +233,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#ifdef CONFIG_PV
+
case PHYSDEVOP_pirq_eoi_gmfn_v2:
case PHYSDEVOP_pirq_eoi_gmfn_v1: {
struct physdev_pirq_eoi_gmfn info;
@@ -281,6 +283,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#endif /* CONFIG_PV */
+
case PHYSDEVOP_irq_status_query: {
struct physdev_irq_status_query irq_status_query;
ret = -EFAULT;
@@ -379,6 +383,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#ifdef CONFIG_PV
+
case PHYSDEVOP_apic_read: {
struct physdev_apic apic;
ret = -EFAULT;
@@ -526,6 +532,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#endif /* CONFIG_PV */
+
case PHYSDEVOP_pci_mmcfg_reserved: {
struct physdev_pci_mmcfg_reserved info;
@@ -560,6 +568,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#ifdef CONFIG_PV
+
case PHYSDEVOP_restore_msi: {
struct physdev_restore_msi restore_msi;
struct pci_dev *pdev;
@@ -591,6 +601,8 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
break;
}
+#endif /* CONFIG_PV */
+
case PHYSDEVOP_setup_gsi: {
struct physdev_setup_gsi setup_gsi;
@@ -610,6 +622,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
setup_gsi.polarity);
break;
}
+
case PHYSDEVOP_get_free_pirq: {
struct physdev_get_free_pirq out;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -644,13 +644,6 @@ static XSM_INLINE int xsm_mem_sharing_op
return xsm_default_action(action, current->domain, cd);
}
-static XSM_INLINE int xsm_apic(
- XSM_DEFAULT_ARG struct domain *d, int cmd)
-{
- XSM_ASSERT_ACTION(XSM_PRIV);
- return xsm_default_action(action, d, NULL);
-}
-
static XSM_INLINE int xsm_machine_memory_map(XSM_DEFAULT_VOID)
{
XSM_ASSERT_ACTION(XSM_PRIV);
@@ -666,6 +659,13 @@ static XSM_INLINE int xsm_domain_memory_
#ifdef CONFIG_PV
+static XSM_INLINE int xsm_apic(
+ XSM_DEFAULT_ARG struct domain *d, int cmd)
+{
+ XSM_ASSERT_ACTION(XSM_PRIV);
+ return xsm_default_action(action, d, NULL);
+}
+
static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
{
XSM_ASSERT_ACTION(XSM_PRIV);
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -131,10 +131,10 @@ XSM_HOOK(int, mem_sharing_op, struct dom
XSM_HOOK(int, platform_op, uint32_t)
#ifdef CONFIG_X86
-XSM_HOOK(int, apic, struct domain *, int)
XSM_HOOK(int, machine_memory_map)
XSM_HOOK(int, domain_memory_map, struct domain *)
#ifdef CONFIG_PV
+XSM_HOOK(int, apic, struct domain *, int)
XSM_HOOK(int, do_mca)
XSM_HOOK(int, mmu_update, struct domain *, struct domain *, struct domain *,
uint32_t)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1750,6 +1750,19 @@ static int cf_check flask_mem_sharing_op
}
#endif
+static int cf_check flask_machine_memory_map(void)
+{
+ return avc_current_has_perm(SECINITSID_XEN, SECCLASS_MMU, MMU__MEMORYMAP,
+ NULL);
+}
+
+static int cf_check flask_domain_memory_map(struct domain *d)
+{
+ return current_has_perm(d, SECCLASS_MMU, MMU__MEMORYMAP);
+}
+
+#ifdef CONFIG_PV
+
static int cf_check flask_apic(struct domain *d, int cmd)
{
uint32_t perm;
@@ -1770,18 +1783,6 @@ static int cf_check flask_apic(struct do
return domain_has_xen(d, perm);
}
-static int cf_check flask_machine_memory_map(void)
-{
- return avc_current_has_perm(SECINITSID_XEN, SECCLASS_MMU, MMU__MEMORYMAP, NULL);
-}
-
-static int cf_check flask_domain_memory_map(struct domain *d)
-{
- return current_has_perm(d, SECCLASS_MMU, MMU__MEMORYMAP);
-}
-
-#ifdef CONFIG_PV
-
static int cf_check flask_do_mca(void)
{
return domain_has_xen(current->domain, XEN__MCA_OP);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 05/14] XSM: make Argo hooks well-formed ones
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (3 preceding siblings ...)
2026-08-17 8:52 ` [PATCH v2 04/14] x86: restrict PHYSDEVOP_* when PV=n Jan Beulich
@ 2026-08-17 8:53 ` Jan Beulich
2026-08-17 8:53 ` [PATCH v2 06/14] XSM: fold xsm_{,un}map_domain_pirq() hooks Jan Beulich
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:53 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Jason Andryuk, Andrew Cooper, Julien Grall,
Stefano Stabellini, Anthony PERARD, Michal Orzel,
Roger Pau Monné
For whatever reason they didn't have an xsm_default_t first argument (to
cope with XSM=n mode), making it impossible to (easily) cover them in
xsm/hooks.h.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Jason Andryuk <jason.andryuk@amd.com>
---
v2: Drop uses of current->domain from dummy handlers. Move const-ification
in xsm_default_action() to a separate patch. Re-base over re-ordering
of series.
--- a/xen/common/argo.c
+++ b/xen/common/argo.c
@@ -1341,7 +1341,7 @@ fill_ring_data(const struct domain *curr
* Don't supply information about rings that a guest is not
* allowed to send to.
*/
- ret = xsm_argo_send(currd, dst_d);
+ ret = xsm_argo_send(XSM_HOOK, currd, dst_d);
if ( ret )
goto out;
@@ -1666,8 +1666,9 @@ register_ring(struct domain *currd,
if ( reg.partner_id == XEN_ARGO_DOMID_ANY )
{
- ret = opt_argo_mac_permissive ? xsm_argo_register_any_source(currd) :
- -EPERM;
+ ret = opt_argo_mac_permissive
+ ? xsm_argo_register_any_source(XSM_HOOK, currd)
+ : -EPERM;
if ( ret )
return ret;
}
@@ -1680,7 +1681,7 @@ register_ring(struct domain *currd,
return -ESRCH;
}
- ret = xsm_argo_register_single_source(currd, dst_d);
+ ret = xsm_argo_register_single_source(XSM_HOOK, currd, dst_d);
if ( ret )
goto out;
@@ -2002,7 +2003,7 @@ sendv(struct domain *src_d, xen_argo_add
if ( !dst_d )
return -ESRCH;
- ret = xsm_argo_send(src_d, dst_d);
+ ret = xsm_argo_send(XSM_HOOK, src_d, dst_d);
if ( ret )
{
gprintk(XENLOG_ERR, "argo: XSM REJECTED %i -> %i\n",
@@ -2100,7 +2101,7 @@ do_argo_op(unsigned int cmd, XEN_GUEST_H
if ( unlikely(!opt_argo) )
return -EOPNOTSUPP;
- rc = xsm_argo_enable(currd);
+ rc = xsm_argo_enable(XSM_HOOK, currd);
if ( rc )
return rc;
@@ -2242,7 +2243,7 @@ compat_argo_op(unsigned int cmd, XEN_GUE
if ( unlikely(!opt_argo) )
return -EOPNOTSUPP;
- rc = xsm_argo_enable(currd);
+ rc = xsm_argo_enable(XSM_HOOK, currd);
if ( rc )
return rc;
@@ -2307,7 +2308,7 @@ argo_init(struct domain *d)
{
struct argo_domain *argo;
- if ( !opt_argo || xsm_argo_enable(d) )
+ if ( !opt_argo || xsm_argo_enable(XSM_HOOK, d) )
{
argo_dprintk("argo disabled, domid: %u\n", d->domain_id);
return 0;
@@ -2365,8 +2366,8 @@ argo_soft_reset(struct domain *d)
wildcard_rings_pending_remove(d);
/*
- * Since neither opt_argo or xsm_argo_enable(d) can change at runtime,
- * if d->argo is true then both opt_argo and xsm_argo_enable(d) must be
+ * Since neither opt_argo nor xsm_argo_enable() can change at runtime,
+ * if d->argo is true then both opt_argo and xsm_argo_enable() must be
* true, and we can assume that init is allowed to proceed again here.
*/
argo_domain_init(d->argo);
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -751,27 +751,32 @@ static XSM_INLINE int xsm_dm_op(XSM_DEFA
#endif
#ifdef CONFIG_ARGO
-static XSM_INLINE int xsm_argo_enable(const struct domain *d)
+
+static XSM_INLINE int xsm_argo_enable(XSM_DEFAULT_ARG const struct domain *d)
{
- return 0;
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, d, NULL);
}
static XSM_INLINE int xsm_argo_register_single_source(
- const struct domain *d, const struct domain *t)
+ XSM_DEFAULT_ARG const struct domain *d, const struct domain *t)
{
- return 0;
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, d, t);
}
static XSM_INLINE int xsm_argo_register_any_source(
- const struct domain *d)
+ XSM_DEFAULT_ARG const struct domain *d)
{
- return 0;
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, d, NULL);
}
static XSM_INLINE int xsm_argo_send(
- const struct domain *d, const struct domain *t)
+ XSM_DEFAULT_ARG const struct domain *d, const struct domain *t)
{
- return 0;
+ XSM_ASSERT_ACTION(XSM_HOOK);
+ return xsm_default_action(action, d, t);
}
#endif /* CONFIG_ARGO */
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -161,6 +161,14 @@ XSM_HOOK(int, do_xsm_op, XEN_GUEST_HANDL
XSM_HOOK(int, do_compat_op, XEN_GUEST_HANDLE_PARAM(void))
#endif
+#ifdef CONFIG_ARGO
+XSM_HOOK(int, argo_enable, const struct domain *)
+XSM_HOOK(int, argo_register_single_source, const struct domain *,
+ const struct domain *)
+XSM_HOOK(int, argo_register_any_source, const struct domain *)
+XSM_HOOK(int, argo_send, const struct domain *, const struct domain *)
+#endif
+
#undef XSM_HOOK0
#undef XSM_HOOK1
#undef XSM_HOOK2
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -85,14 +85,6 @@ struct xsm_ops {
char *(*show_security_evtchn)(struct domain *d, const struct evtchn *chn);
char *(*show_irq_sid)(int irq);
-
-#ifdef CONFIG_ARGO
- int (*argo_enable)(const struct domain *d);
- int (*argo_register_single_source)(const struct domain *d,
- const struct domain *t);
- int (*argo_register_any_source)(const struct domain *d);
- int (*argo_send)(const struct domain *d, const struct domain *t);
-#endif
};
#ifdef CONFIG_XSM
@@ -196,30 +188,6 @@ static inline char *xsm_show_irq_sid(int
return alternative_call(xsm_ops.show_irq_sid, irq);
}
-#ifdef CONFIG_ARGO
-static inline int xsm_argo_enable(const struct domain *d)
-{
- return alternative_call(xsm_ops.argo_enable, d);
-}
-
-static inline int xsm_argo_register_single_source(
- const struct domain *d, const struct domain *t)
-{
- return alternative_call(xsm_ops.argo_register_single_source, d, t);
-}
-
-static inline int xsm_argo_register_any_source(const struct domain *d)
-{
- return alternative_call(xsm_ops.argo_register_any_source, d);
-}
-
-static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
-{
- return alternative_call(xsm_ops.argo_send, d, t);
-}
-
-#endif /* CONFIG_ARGO */
-
#endif /* XSM_NO_WRAPPERS */
#ifdef CONFIG_MULTIBOOT
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -35,13 +35,6 @@ static const struct xsm_ops __initconst_
.show_security_evtchn = xsm_show_security_evtchn,
.show_irq_sid = xsm_show_irq_sid,
-
-#ifdef CONFIG_ARGO
- .argo_enable = xsm_argo_enable,
- .argo_register_single_source = xsm_argo_register_single_source,
- .argo_register_any_source = xsm_argo_register_any_source,
- .argo_send = xsm_argo_send,
-#endif
};
void __init xsm_fixup_ops(struct xsm_ops *ops)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1972,13 +1972,6 @@ static const struct xsm_ops __initconst_
.show_security_evtchn = flask_show_security_evtchn,
.show_irq_sid = flask_show_irq_sid,
-
-#ifdef CONFIG_ARGO
- .argo_enable = flask_argo_enable,
- .argo_register_single_source = flask_argo_register_single_source,
- .argo_register_any_source = flask_argo_register_any_source,
- .argo_send = flask_argo_send,
-#endif
};
const struct xsm_ops *__init flask_init(
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 06/14] XSM: fold xsm_{,un}map_domain_pirq() hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (4 preceding siblings ...)
2026-08-17 8:53 ` [PATCH v2 05/14] XSM: make Argo hooks well-formed ones Jan Beulich
@ 2026-08-17 8:53 ` Jan Beulich
2026-08-17 8:54 ` [PATCH v2 07/14] x86: type-correct last parameter of map_domain_pirq() Jan Beulich
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:53 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Teddy Astie, Roger Pau Monné
Like other resource management hooks they are different in just "add
resource" vs "remove resource". Hence like in other cases a single hook
can easily serve both purposes. Rename hook and functions to fit
xsm_io{mem,port}_mapping().
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Rename hook, functions, and new parameter.
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -109,7 +109,7 @@ int physdev_map_pirq(struct domain *d, i
return physdev_hvm_map_pirq(d, type, index, pirq_p);
}
- ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
+ ret = xsm_pirq_mapping(XSM_DM_PRIV, d, true);
if ( ret )
return ret;
@@ -142,7 +142,7 @@ int physdev_unmap_pirq(struct domain *d,
int ret = 0;
if ( d != current->domain || !is_hvm_domain(d) || !has_pirq(d) )
- ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
+ ret = xsm_pirq_mapping(XSM_DM_PRIV, d, false);
if ( ret )
return ret;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -460,15 +460,8 @@ static XSM_INLINE char *xsm_show_irq_sid
#ifdef CONFIG_HAS_PIRQ
-static XSM_INLINE int xsm_map_domain_pirq(
- XSM_DEFAULT_ARG struct domain *d)
-{
- XSM_ASSERT_ACTION(XSM_DM_PRIV);
- return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_unmap_domain_pirq(
- XSM_DEFAULT_ARG struct domain *d)
+static XSM_INLINE int xsm_pirq_mapping(
+ XSM_DEFAULT_ARG struct domain *d, bool map)
{
XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -68,8 +68,7 @@ XSM_HOOK(int, kexec)
XSM_HOOK(int, schedop_shutdown, struct domain *, struct domain *)
#ifdef CONFIG_HAS_PIRQ
-XSM_HOOK(int, map_domain_pirq, struct domain *)
-XSM_HOOK(int, unmap_domain_pirq, struct domain *)
+XSM_HOOK(int, pirq_mapping, struct domain *, bool)
#endif
XSM_HOOK(int, map_domain_irq, struct domain *, int, const void *)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1022,14 +1022,9 @@ static char *cf_check flask_show_irq_sid
#ifdef CONFIG_HAS_PIRQ
-static int cf_check flask_map_domain_pirq(struct domain *d)
+static int cf_check flask_pirq_mapping(struct domain *d, bool map)
{
- return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
-}
-
-static int cf_check flask_unmap_domain_pirq(struct domain *d)
-{
- return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+ return current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(map));
}
#endif /* CONFIG_HAS_PIRQ */
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 07/14] x86: type-correct last parameter of map_domain_pirq()
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (5 preceding siblings ...)
2026-08-17 8:53 ` [PATCH v2 06/14] XSM: fold xsm_{,un}map_domain_pirq() hooks Jan Beulich
@ 2026-08-17 8:54 ` Jan Beulich
2026-08-17 8:54 ` [PATCH v2 08/14] XSM: pass just SBDF to xsm_{,un}map_domain_irq() Jan Beulich
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:54 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Andrew Cooper, Teddy Astie, Roger Pau Monné
This was meant to allow for non-MSI data to be passed if necessary, but
the way XSM/Flask uses the (propagated) argument that's not going to work
anyway without further adjustments. As no secondary use has surfaced in
many years, switch to using the correct type.
Leave XSM alone, as that'll be changed subsequently anyway (to then also
no longer use plain void).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/include/asm/irq.h
+++ b/xen/arch/x86/include/asm/irq.h
@@ -27,6 +27,7 @@ typedef struct {
} vmask_t;
struct irq_desc;
+struct msi_info;
/*
* Xen logic for moving interrupts around CPUs allows manipulating interrupts
@@ -161,7 +162,7 @@ struct arch_pirq {
int pirq_shared(struct domain *d , int pirq);
int map_domain_pirq(struct domain *d, int pirq, int irq, int type,
- void *data);
+ struct msi_info *msi);
int unmap_domain_pirq(struct domain *d, int pirq);
int get_free_pirq(struct domain *d, int type);
int get_free_pirqs(struct domain *d, unsigned int nr);
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2180,7 +2180,7 @@ int get_free_pirqs(struct domain *d, uns
#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
int map_domain_pirq(
- struct domain *d, int pirq, int irq, int type, void *data)
+ struct domain *d, int pirq, int irq, int type, struct msi_info *msi)
{
int ret = 0;
int old_irq, old_pirq;
@@ -2214,7 +2214,7 @@ int map_domain_pirq(
return 0;
}
- ret = xsm_map_domain_irq(XSM_HOOK, d, irq, data);
+ ret = xsm_map_domain_irq(XSM_HOOK, d, irq, msi);
if ( ret )
{
dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
@@ -2245,7 +2245,6 @@ int map_domain_pirq(
if ( type == MAP_PIRQ_TYPE_MSI || type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- struct msi_info *msi = (struct msi_info *)data;
struct msi_desc *msi_desc;
struct pci_dev *pdev;
unsigned int nr = 0;
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 08/14] XSM: pass just SBDF to xsm_{,un}map_domain_irq()
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (6 preceding siblings ...)
2026-08-17 8:54 ` [PATCH v2 07/14] x86: type-correct last parameter of map_domain_pirq() Jan Beulich
@ 2026-08-17 8:54 ` Jan Beulich
2026-08-17 8:55 ` [PATCH v2 09/14] XSM: fold xsm_{,un}map_domain_irq() hooks Jan Beulich
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:54 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Teddy Astie, Roger Pau Monné
That's what Flask needs, and by unifying the hooks flask_map_domain_msi()
can then also serve both flask_{,un}map_domain_irq().
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
How come Arm doesn't use xsm_unmap_domain_irq()?
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2214,7 +2214,7 @@ int map_domain_pirq(
return 0;
}
- ret = xsm_map_domain_irq(XSM_HOOK, d, irq, msi);
+ ret = xsm_map_domain_irq(XSM_HOOK, d, irq, msi ? &msi->sbdf : NULL);
if ( ret )
{
dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
@@ -2442,7 +2442,7 @@ int unmap_domain_pirq(struct domain *d,
*/
if ( !d->is_dying )
ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
- msi_desc ? msi_desc->dev : NULL);
+ msi_desc ? &msi_desc->dev->sbdf : NULL);
if ( ret )
goto done;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -470,7 +470,7 @@ static XSM_INLINE int xsm_pirq_mapping(
#endif /* CONFIG_HAS_PIRQ */
static XSM_INLINE int xsm_map_domain_irq(
- XSM_DEFAULT_ARG struct domain *d, int irq, const void *data)
+ XSM_DEFAULT_ARG struct domain *d, int irq, const pci_sbdf_t *sbdf)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
@@ -491,7 +491,7 @@ static XSM_INLINE int xsm_unbind_pt_irq(
}
static XSM_INLINE int xsm_unmap_domain_irq(
- XSM_DEFAULT_ARG struct domain *d, int irq, const void *data)
+ XSM_DEFAULT_ARG struct domain *d, int irq, const pci_sbdf_t *sbdf)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -71,8 +71,8 @@ XSM_HOOK(int, schedop_shutdown, struct d
XSM_HOOK(int, pirq_mapping, struct domain *, bool)
#endif
-XSM_HOOK(int, map_domain_irq, struct domain *, int, const void *)
-XSM_HOOK(int, unmap_domain_irq, struct domain *, int, const void *)
+XSM_HOOK(int, map_domain_irq, struct domain *, int, const pci_sbdf_t *)
+XSM_HOOK(int, unmap_domain_irq, struct domain *, int, const pci_sbdf_t *)
XSM_HOOK(int, bind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
XSM_HOOK(int, unbind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1030,17 +1030,14 @@ static int cf_check flask_pirq_mapping(s
#endif /* CONFIG_HAS_PIRQ */
static int flask_map_domain_msi (
- struct domain *d, int irq, const void *data, uint32_t *sid,
+ struct domain *d, int irq, pci_sbdf_t sbdf, uint32_t *sid,
struct avc_audit_data *ad)
{
#ifdef CONFIG_HAS_PCI_MSI
- const struct msi_info *msi = data;
- uint32_t machine_bdf = msi->sbdf.sbdf;
-
AVC_AUDIT_DATA_INIT(ad, DEV);
- ad->device = machine_bdf;
+ ad->device = sbdf.sbdf;
- return security_device_sid(machine_bdf, sid);
+ return security_device_sid(sbdf.sbdf, sid);
#else
return -EINVAL;
#endif
@@ -1066,15 +1063,15 @@ static uint32_t flask_iommu_resource_use
}
static int cf_check flask_map_domain_irq(
- struct domain *d, int irq, const void *data)
+ struct domain *d, int irq, const pci_sbdf_t *sbdf)
{
uint32_t sid, dsid;
int rc = -EPERM;
struct avc_audit_data ad;
uint32_t dperm = flask_iommu_resource_use_perm(d);
- if ( irq >= nr_static_irqs && data )
- rc = flask_map_domain_msi(d, irq, data, &sid, &ad);
+ if ( irq >= nr_static_irqs && sbdf )
+ rc = flask_map_domain_msi(d, irq, *sbdf, &sid, &ad);
else
rc = get_irq_sid(irq, &sid, &ad);
@@ -1091,32 +1088,15 @@ static int cf_check flask_map_domain_irq
return rc;
}
-static int flask_unmap_domain_msi (
- struct domain *d, int irq, const void *data, uint32_t *sid,
- struct avc_audit_data *ad)
-{
-#ifdef CONFIG_HAS_PCI_MSI
- const struct pci_dev *pdev = data;
- uint32_t machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
-
- AVC_AUDIT_DATA_INIT(ad, DEV);
- ad->device = machine_bdf;
-
- return security_device_sid(machine_bdf, sid);
-#else
- return -EINVAL;
-#endif
-}
-
static int cf_check flask_unmap_domain_irq(
- struct domain *d, int irq, const void *data)
+ struct domain *d, int irq, const pci_sbdf_t *sbdf)
{
uint32_t sid;
int rc = -EPERM;
struct avc_audit_data ad;
- if ( irq >= nr_static_irqs && data )
- rc = flask_unmap_domain_msi(d, irq, data, &sid, &ad);
+ if ( irq >= nr_static_irqs && sbdf )
+ rc = flask_map_domain_msi(d, irq, *sbdf, &sid, &ad);
else
rc = get_irq_sid(irq, &sid, &ad);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 09/14] XSM: fold xsm_{,un}map_domain_irq() hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (7 preceding siblings ...)
2026-08-17 8:54 ` [PATCH v2 08/14] XSM: pass just SBDF to xsm_{,un}map_domain_irq() Jan Beulich
@ 2026-08-17 8:55 ` Jan Beulich
2026-08-17 8:56 ` [PATCH v2 10/14] XSM: fold xsm_{,un}bind_pt_irq() hooks Jan Beulich
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:55 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Teddy Astie, Roger Pau Monné
Like other resource management hooks they are (now) mainly different in
"add resource" vs "remove resource". Hence like in other cases a single
hook can easily serve both purposes, with minor tweaking of
flask_map_domain_irq(). While adjusting that function, also defer the
setting of local variables only needed in the "map" case.
Rename hook and functions to fit xsm_{io{mem,port},pirq}_mapping().
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix inverted part of conditional in flask_map_domain_irq(). Rename
hook, functions, and new parameter.
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -100,7 +100,7 @@ long arch_do_domctl(struct xen_domctl *d
* done by the 2 hypercalls for consistency with other
* architectures.
*/
- rc = xsm_map_domain_irq(XSM_HOOK, d, irq, NULL);
+ rc = xsm_irq_mapping(XSM_HOOK, d, irq, NULL, true);
if ( rc )
return rc;
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2214,7 +2214,7 @@ int map_domain_pirq(
return 0;
}
- ret = xsm_map_domain_irq(XSM_HOOK, d, irq, msi ? &msi->sbdf : NULL);
+ ret = xsm_irq_mapping(XSM_HOOK, d, irq, msi ? &msi->sbdf : NULL, true);
if ( ret )
{
dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
@@ -2441,8 +2441,8 @@ int unmap_domain_pirq(struct domain *d,
* domain. Skip the XSM check since this is a Xen-initiated action.
*/
if ( !d->is_dying )
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
- msi_desc ? &msi_desc->dev->sbdf : NULL);
+ ret = xsm_irq_mapping(XSM_HOOK, d, irq,
+ msi_desc ? &msi_desc->dev->sbdf : NULL, false);
if ( ret )
goto done;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -469,8 +469,9 @@ static XSM_INLINE int xsm_pirq_mapping(
#endif /* CONFIG_HAS_PIRQ */
-static XSM_INLINE int xsm_map_domain_irq(
- XSM_DEFAULT_ARG struct domain *d, int irq, const pci_sbdf_t *sbdf)
+static XSM_INLINE int xsm_irq_mapping(
+ XSM_DEFAULT_ARG struct domain *d, int irq, const pci_sbdf_t *sbdf,
+ bool map)
{
XSM_ASSERT_ACTION(XSM_HOOK);
return xsm_default_action(action, current->domain, d);
@@ -490,13 +491,6 @@ static XSM_INLINE int xsm_unbind_pt_irq(
return xsm_default_action(action, current->domain, d);
}
-static XSM_INLINE int xsm_unmap_domain_irq(
- XSM_DEFAULT_ARG struct domain *d, int irq, const pci_sbdf_t *sbdf)
-{
- XSM_ASSERT_ACTION(XSM_HOOK);
- return xsm_default_action(action, current->domain, d);
-}
-
static XSM_INLINE int xsm_irq_permission(
XSM_DEFAULT_ARG struct domain *d, int pirq, bool allow)
{
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -71,8 +71,7 @@ XSM_HOOK(int, schedop_shutdown, struct d
XSM_HOOK(int, pirq_mapping, struct domain *, bool)
#endif
-XSM_HOOK(int, map_domain_irq, struct domain *, int, const pci_sbdf_t *)
-XSM_HOOK(int, unmap_domain_irq, struct domain *, int, const pci_sbdf_t *)
+XSM_HOOK(int, irq_mapping, struct domain *, int, const pci_sbdf_t *, bool)
XSM_HOOK(int, bind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
XSM_HOOK(int, unbind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1062,13 +1062,12 @@ static uint32_t flask_iommu_resource_use
return perm;
}
-static int cf_check flask_map_domain_irq(
- struct domain *d, int irq, const pci_sbdf_t *sbdf)
+static int cf_check flask_irq_mapping(
+ struct domain *d, int irq, const pci_sbdf_t *sbdf, bool map)
{
- uint32_t sid, dsid;
+ uint32_t sid, dsid, dperm;
int rc = -EPERM;
struct avc_audit_data ad;
- uint32_t dperm = flask_iommu_resource_use_perm(d);
if ( irq >= nr_static_irqs && sbdf )
rc = flask_map_domain_msi(d, irq, *sbdf, &sid, &ad);
@@ -1078,33 +1077,16 @@ static int cf_check flask_map_domain_irq
if ( rc )
return rc;
- dsid = domain_sid(d);
-
- rc = avc_current_has_perm(sid, SECCLASS_RESOURCE, RESOURCE__ADD_IRQ, &ad);
- if ( rc )
+ rc = avc_current_has_perm(sid, SECCLASS_RESOURCE,
+ map ? RESOURCE__ADD_IRQ : RESOURCE__REMOVE_IRQ,
+ &ad);
+ if ( rc || !map )
return rc;
- rc = avc_has_perm(dsid, sid, SECCLASS_RESOURCE, dperm, &ad);
- return rc;
-}
-
-static int cf_check flask_unmap_domain_irq(
- struct domain *d, int irq, const pci_sbdf_t *sbdf)
-{
- uint32_t sid;
- int rc = -EPERM;
- struct avc_audit_data ad;
-
- if ( irq >= nr_static_irqs && sbdf )
- rc = flask_map_domain_msi(d, irq, *sbdf, &sid, &ad);
- else
- rc = get_irq_sid(irq, &sid, &ad);
-
- if ( rc )
- return rc;
+ dsid = domain_sid(d);
+ dperm = flask_iommu_resource_use_perm(d);
- rc = avc_current_has_perm(sid, SECCLASS_RESOURCE, RESOURCE__REMOVE_IRQ, &ad);
- return rc;
+ return avc_has_perm(dsid, sid, SECCLASS_RESOURCE, dperm, &ad);
}
static int cf_check flask_bind_pt_irq(
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 10/14] XSM: fold xsm_{,un}bind_pt_irq() hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (8 preceding siblings ...)
2026-08-17 8:55 ` [PATCH v2 09/14] XSM: fold xsm_{,un}map_domain_irq() hooks Jan Beulich
@ 2026-08-17 8:56 ` Jan Beulich
2026-08-17 8:56 ` [PATCH v2 11/14] XSM: convert remaining event channel hooks Jan Beulich
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:56 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Julien Grall, Stefano Stabellini, Volodymyr Babchuk,
Bertrand Marquis, Michal Orzel, Andrew Cooper, Teddy Astie,
Roger Pau Monné
Like other resource management hooks they are mainly different in "add
resource" vs "remove resource". Hence like in other cases a single hook
can easily serve both purposes, with minor tweaking of
flask_bind_pt_irq(). While adjusting that function, also defer the setting
of "dperm", which is only needed in the "map" case.
Rename hook and functions to fit xsm_{io{mem,port},{p,}irq}_mapping().
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix inverted part of conditional in flask_bind_pt_irq(). Rename hook,
functions, and new parameter.
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -104,7 +104,7 @@ long arch_do_domctl(struct xen_domctl *d
if ( rc )
return rc;
- rc = xsm_bind_pt_irq(XSM_DM_PRIV, d, bind);
+ rc = xsm_pt_irq_binding(XSM_DM_PRIV, d, bind, true);
if ( rc )
return rc;
@@ -140,7 +140,7 @@ long arch_do_domctl(struct xen_domctl *d
if ( irq != virq )
return -EINVAL;
- rc = xsm_unbind_pt_irq(XSM_DM_PRIV, d, bind);
+ rc = xsm_pt_irq_binding(XSM_DM_PRIV, d, bind, false);
if ( rc )
return rc;
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -622,7 +622,7 @@ long arch_do_domctl(
if ( !is_hvm_domain(d) )
break;
- ret = xsm_bind_pt_irq(XSM_DM_PRIV, d, bind);
+ ret = xsm_pt_irq_binding(XSM_DM_PRIV, d, bind, true);
if ( ret )
break;
@@ -660,7 +660,7 @@ long arch_do_domctl(
if ( !is_hvm_domain(d) )
break;
- ret = xsm_unbind_pt_irq(XSM_DM_PRIV, d, bind);
+ ret = xsm_pt_irq_binding(XSM_DM_PRIV, d, bind, false);
if ( ret )
break;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -477,15 +477,9 @@ static XSM_INLINE int xsm_irq_mapping(
return xsm_default_action(action, current->domain, d);
}
-static XSM_INLINE int xsm_bind_pt_irq(
- XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
- XSM_ASSERT_ACTION(XSM_DM_PRIV);
- return xsm_default_action(action, current->domain, d);
-}
-
-static XSM_INLINE int xsm_unbind_pt_irq(
- XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+static XSM_INLINE int xsm_pt_irq_binding(
+ XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind,
+ bool map)
{
XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -72,8 +72,8 @@ XSM_HOOK(int, pirq_mapping, struct domai
#endif
XSM_HOOK(int, irq_mapping, struct domain *, int, const pci_sbdf_t *, bool)
-XSM_HOOK(int, bind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
-XSM_HOOK(int, unbind_pt_irq, struct domain *, struct xen_domctl_bind_pt_irq *)
+XSM_HOOK(int, pt_irq_binding, struct domain *, struct xen_domctl_bind_pt_irq *,
+ bool)
XSM_HOOK(int, irq_permission, struct domain *, int, bool)
XSM_HOOK(int, iomem_permission, struct domain *, uint64_t, uint64_t, bool)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1089,17 +1089,16 @@ static int cf_check flask_irq_mapping(
return avc_has_perm(dsid, sid, SECCLASS_RESOURCE, dperm, &ad);
}
-static int cf_check flask_bind_pt_irq(
- struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+static int cf_check flask_pt_irq_binding(
+ struct domain *d, struct xen_domctl_bind_pt_irq *bind, bool map)
{
- uint32_t dsid, rsid;
+ uint32_t dsid, rsid, dperm;
int rc = -EPERM;
int irq;
struct avc_audit_data ad;
- uint32_t dperm = flask_iommu_resource_use_perm(d);
- rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
- if ( rc )
+ rc = current_has_perm(d, SECCLASS_RESOURCE, resource_to_perm(map));
+ if ( rc || !map )
return rc;
irq = domain_pirq_to_irq(d, bind->machine_irq);
@@ -1113,13 +1112,9 @@ static int cf_check flask_bind_pt_irq(
return rc;
dsid = domain_sid(d);
- return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
-}
+ dperm = flask_iommu_resource_use_perm(d);
-static int cf_check flask_unbind_pt_irq(
- struct domain *d, struct xen_domctl_bind_pt_irq *bind)
-{
- return current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+ return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
}
static int cf_check flask_irq_permission(
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 11/14] XSM: convert remaining event channel hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (9 preceding siblings ...)
2026-08-17 8:56 ` [PATCH v2 10/14] XSM: fold xsm_{,un}bind_pt_irq() hooks Jan Beulich
@ 2026-08-17 8:56 ` Jan Beulich
2026-08-17 8:57 ` [PATCH v2 12/14] XSM: convert remaining domain-related hooks Jan Beulich
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:56 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Julien Grall, Stefano Stabellini,
Anthony PERARD, Michal Orzel, Roger Pau Monné
Make them follow the standard scheme, i.e. taking xsm_default_t as first
argument at call sites. This way they can be covered by the recently
introduced hook machinery.
While there, uniformly convert struct evtchn chn[] notation to pointer
form, as the (nicer) array representation is harder to make usable with
the hooks.h logic.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: New.
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -159,7 +159,7 @@ static void free_evtchn_bucket(struct do
if ( !bucket )
return;
- xsm_free_security_evtchns(bucket, EVTCHNS_PER_BUCKET);
+ xsm_free_security_evtchns(XSM_HOOK, bucket, EVTCHNS_PER_BUCKET);
xfree(bucket);
}
@@ -172,7 +172,7 @@ static struct evtchn *alloc_evtchn_bucke
if ( !chn )
goto err;
- if ( xsm_alloc_security_evtchns(chn, EVTCHNS_PER_BUCKET) )
+ if ( xsm_alloc_security_evtchns(XSM_HOOK, chn, EVTCHNS_PER_BUCKET) )
goto err;
for ( i = 0; i < EVTCHNS_PER_BUCKET; i++ )
@@ -297,7 +297,7 @@ void evtchn_free(struct domain *d, struc
chn->notify_vcpu_id = 0;
chn->xen_consumer = 0;
- xsm_evtchn_close_post(chn);
+ xsm_evtchn_close_post(XSM_HOOK, chn);
}
static int evtchn_get_port(struct domain *d, evtchn_port_t port)
@@ -1779,7 +1779,7 @@ static void domain_dump_evtchn_info(stru
break;
}
- ssid = xsm_show_security_evtchn(d, chn);
+ ssid = xsm_show_security_evtchn(XSM_HOOK, d, chn);
if (ssid) {
printk(" Z=%s\n", ssid);
xfree(ssid);
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -311,8 +311,10 @@ static XSM_INLINE int xsm_evtchn_interdo
return xsm_default_action(action, d1, d2);
}
-static XSM_INLINE void xsm_evtchn_close_post(struct evtchn *chn)
-{}
+static XSM_INLINE void xsm_evtchn_close_post(XSM_DEFAULT_ARG struct evtchn *chn)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+}
static XSM_INLINE int xsm_evtchn_send(
XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn)
@@ -336,18 +338,22 @@ static XSM_INLINE int xsm_evtchn_reset(
}
static XSM_INLINE int xsm_alloc_security_evtchns(
- struct evtchn chn[], unsigned int nr)
+ XSM_DEFAULT_ARG struct evtchn *chn, unsigned int nr)
{
+ XSM_ASSERT_ACTION(XSM_HOOK);
return 0;
}
static XSM_INLINE void xsm_free_security_evtchns(
- struct evtchn chn[], unsigned int nr)
-{}
+ XSM_DEFAULT_ARG struct evtchn *chn, unsigned int nr)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+}
static XSM_INLINE char *xsm_show_security_evtchn(
- struct domain *d, const struct evtchn *chn)
+ XSM_DEFAULT_ARG struct domain *d, const struct evtchn *chn)
{
+ XSM_ASSERT_ACTION(XSM_HOOK);
return NULL;
}
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -34,6 +34,11 @@ XSM_HOOK(int, evtchn_interdomain, struct
XSM_HOOK(int, evtchn_send, struct domain *, struct evtchn *)
XSM_HOOK(int, evtchn_status, struct domain *, struct evtchn *)
XSM_HOOK(int, evtchn_reset, struct domain *, struct domain *)
+XSM_HOOK(void, evtchn_close_post, struct evtchn *)
+XSM_HOOK(int, alloc_security_evtchns, struct evtchn *, unsigned int)
+XSM_HOOK(void, free_security_evtchns, struct evtchn *, unsigned int)
+XSM_HOOK(pchar_t, show_security_evtchn, struct domain *,
+ const struct evtchn *)
#ifdef CONFIG_GRANT_TABLE
XSM_HOOK(int, grant_mapref, struct domain *, struct domain *, uint32_t)
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -21,6 +21,9 @@
/* policy magic number (defined by XSM_MAGIC) */
typedef uint32_t xsm_magic_t;
+/* Auxiliary type(s) for use in hook definitions. */
+typedef char *pchar_t;
+
#ifdef CONFIG_XSM_FLASK
#define XSM_MAGIC 0xf97cff8cU
#else
@@ -76,13 +79,8 @@ struct xsm_ops {
#include "hooks.h"
- void (*evtchn_close_post)(struct evtchn *chn);
-
int (*alloc_security_domain)(struct domain *d);
void (*free_security_domain)(struct domain *d);
- int (*alloc_security_evtchns)(struct evtchn chn[], unsigned int nr);
- void (*free_security_evtchns)(struct evtchn chn[], unsigned int nr);
- char *(*show_security_evtchn)(struct domain *d, const struct evtchn *chn);
char *(*show_irq_sid)(int irq);
};
@@ -104,8 +102,9 @@ static inline void xsm_security_domainin
alternative_vcall(xsm_ops.security_domaininfo, d, info);
}
-#define XSM_ALT_void alternative_vcall
-#define XSM_ALT_int return alternative_call
+#define XSM_ALT_void alternative_vcall
+#define XSM_ALT_int return alternative_call
+#define XSM_ALT_pchar_t return alternative_call
#define XSM_HOOK0(rtype, name) \
static inline rtype xsm_ ## name(xsm_default_t def) \
@@ -150,11 +149,6 @@ static inline rtype xsm_ ## name( \
#include "hooks.h"
-static inline void xsm_evtchn_close_post(struct evtchn *chn)
-{
- alternative_vcall(xsm_ops.evtchn_close_post, chn);
-}
-
static inline int xsm_alloc_security_domain(struct domain *d)
{
return alternative_call(xsm_ops.alloc_security_domain, d);
@@ -165,24 +159,6 @@ static inline void xsm_free_security_dom
alternative_vcall(xsm_ops.free_security_domain, d);
}
-static inline int xsm_alloc_security_evtchns(
- struct evtchn *chn, unsigned int nr)
-{
- return alternative_call(xsm_ops.alloc_security_evtchns, chn, nr);
-}
-
-static inline void xsm_free_security_evtchns(
- struct evtchn *chn, unsigned int nr)
-{
- alternative_vcall(xsm_ops.free_security_evtchns, chn, nr);
-}
-
-static inline char *xsm_show_security_evtchn(
- struct domain *d, const struct evtchn *chn)
-{
- return alternative_call(xsm_ops.show_security_evtchn, d, chn);
-}
-
static inline char *xsm_show_irq_sid(int irq)
{
return alternative_call(xsm_ops.show_irq_sid, irq);
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -26,13 +26,8 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .evtchn_close_post = xsm_evtchn_close_post,
-
.alloc_security_domain = xsm_alloc_security_domain,
.free_security_domain = xsm_free_security_domain,
- .alloc_security_evtchns = xsm_alloc_security_evtchns,
- .free_security_evtchns = xsm_free_security_evtchns,
- .show_security_evtchn = xsm_show_security_evtchn,
.show_irq_sid = xsm_show_irq_sid,
};
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1915,13 +1915,8 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .evtchn_close_post = flask_evtchn_close_post,
-
.alloc_security_domain = flask_domain_alloc_security,
.free_security_domain = flask_domain_free_security,
- .alloc_security_evtchns = flask_alloc_security_evtchns,
- .free_security_evtchns = flask_free_security_evtchns,
- .show_security_evtchn = flask_show_security_evtchn,
.show_irq_sid = flask_show_irq_sid,
};
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 12/14] XSM: convert remaining domain-related hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (10 preceding siblings ...)
2026-08-17 8:56 ` [PATCH v2 11/14] XSM: convert remaining event channel hooks Jan Beulich
@ 2026-08-17 8:57 ` Jan Beulich
2026-08-17 8:58 ` [PATCH v2 13/14] XSM: convert remaining miscellaneous hooks Jan Beulich
2026-08-17 8:58 ` [PATCH RFC v2 14/14] XSM: avoid fragile assumptions in xsm_fixup_ops() Jan Beulich
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:57 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Andrew Cooper, Julien Grall, Stefano Stabellini,
Anthony PERARD, Michal Orzel, Roger Pau Monné
Make them follow the standard scheme, i.e. taking xsm_default_t as first
argument at call sites. This way they can be covered by the recently
introduced hook machinery.
While there,
- rename flask_domain_{alloc,free}_security() to fit the corresponding
hook names,
- add const to .security_domaininfo()'s first parameter.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: New.
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -760,7 +760,7 @@ static void _domain_destroy(struct domai
free_cpumask_var(d->dirty_cpumask);
- xsm_free_security_domain(d);
+ xsm_free_security_domain(XSM_HOOK, d);
lock_profile_deregister_struct(LOCKPROF_TYPE_PERDOM, d);
@@ -987,7 +987,7 @@ struct domain *domain_create(domid_t dom
d->max_vcpus = config->max_vcpus;
}
- if ( (err = xsm_alloc_security_domain(d)) != 0 )
+ if ( (err = xsm_alloc_security_domain(XSM_HOOK, d)) != 0 )
goto fail;
err = -ENOMEM;
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -91,7 +91,7 @@ void getdomaininfo(struct domain *d, str
(is_hvm_domain(d) ? XEN_DOMINF_hvm_guest : 0) |
d->shutdown_code << XEN_DOMINF_shutdownshift;
- xsm_security_domaininfo(d, info);
+ xsm_security_domaininfo(XSM_HOOK, d, info);
info->tot_pages = domain_tot_pages(d);
info->max_pages = d->max_pages;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -122,8 +122,11 @@ static XSM_INLINE int xsm_set_system_act
}
static XSM_INLINE void xsm_security_domaininfo(
- struct domain *d, struct xen_domctl_getdomaininfo *info)
-{}
+ XSM_DEFAULT_ARG const struct domain *d,
+ struct xen_domctl_getdomaininfo *info)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+}
static XSM_INLINE int xsm_domain_create(
XSM_DEFAULT_ARG struct domain *d, uint32_t ssidref)
@@ -179,13 +182,18 @@ static XSM_INLINE int xsm_sysctl(
return xsm_default_action(action, current->domain, NULL);
}
-static XSM_INLINE int xsm_alloc_security_domain(struct domain *d)
+static XSM_INLINE int xsm_alloc_security_domain(
+ XSM_DEFAULT_ARG struct domain *d)
{
+ XSM_ASSERT_ACTION(XSM_HOOK);
return 0;
}
-static XSM_INLINE void xsm_free_security_domain(struct domain *d)
-{}
+static XSM_INLINE void xsm_free_security_domain(
+ XSM_DEFAULT_ARG struct domain *d)
+{
+ XSM_ASSERT_ACTION(XSM_HOOK);
+}
#ifdef CONFIG_GRANT_TABLE
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -20,6 +20,10 @@
XSM_HOOK(int, domain_create, struct domain *, uint32_t)
XSM_HOOK(int, getdomaininfo, struct domain *)
XSM_HOOK(int, get_domain_state, struct domain *)
+XSM_HOOK(void, security_domaininfo, const struct domain *,
+ struct xen_domctl_getdomaininfo *)
+XSM_HOOK(int, alloc_security_domain, struct domain *)
+XSM_HOOK(void, free_security_domain, struct domain *)
#ifdef CONFIG_SYSCTL
XSM_HOOK(int, sysctl, const struct xen_sysctl *)
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -62,8 +62,6 @@ typedef enum xsm_default xsm_default_t;
*/
struct xsm_ops {
int (*set_system_active)(void);
- void (*security_domaininfo)(struct domain *d,
- struct xen_domctl_getdomaininfo *info);
#define XSM_HOOK0(rtype, name) rtype (*name)(void);
#define XSM_HOOK1(rtype, name, type1) \
@@ -79,9 +77,6 @@ struct xsm_ops {
#include "hooks.h"
- int (*alloc_security_domain)(struct domain *d);
- void (*free_security_domain)(struct domain *d);
-
char *(*show_irq_sid)(int irq);
};
@@ -96,12 +91,6 @@ static inline int xsm_set_system_active(
return alternative_call(xsm_ops.set_system_active);
}
-static inline void xsm_security_domaininfo(
- struct domain *d, struct xen_domctl_getdomaininfo *info)
-{
- alternative_vcall(xsm_ops.security_domaininfo, d, info);
-}
-
#define XSM_ALT_void alternative_vcall
#define XSM_ALT_int return alternative_call
#define XSM_ALT_pchar_t return alternative_call
@@ -149,16 +138,6 @@ static inline rtype xsm_ ## name( \
#include "hooks.h"
-static inline int xsm_alloc_security_domain(struct domain *d)
-{
- return alternative_call(xsm_ops.alloc_security_domain, d);
-}
-
-static inline void xsm_free_security_domain(struct domain *d)
-{
- alternative_vcall(xsm_ops.free_security_domain, d);
-}
-
static inline char *xsm_show_irq_sid(int irq)
{
return alternative_call(xsm_ops.show_irq_sid, irq);
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -15,7 +15,6 @@
static const struct xsm_ops __initconst_cf_clobber dummy_ops = {
.set_system_active = xsm_set_system_active,
- .security_domaininfo = xsm_security_domaininfo,
#define XSM_HOOK0(rtype, name) .name = xsm_ ## name,
#define XSM_HOOK1(rtype, name, ...) XSM_HOOK0(rtype, name)
@@ -26,9 +25,6 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .alloc_security_domain = xsm_alloc_security_domain,
- .free_security_domain = xsm_free_security_domain,
-
.show_irq_sid = xsm_show_irq_sid,
};
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -188,7 +188,7 @@ static int avc_unknown_permission(const
return rc;
}
-static int cf_check flask_domain_alloc_security(struct domain *d)
+static int cf_check flask_alloc_security_domain(struct domain *d)
{
struct domain_security_struct *dsec;
@@ -256,7 +256,7 @@ static int cf_check flask_set_system_act
return 0;
}
-static void cf_check flask_domain_free_security(struct domain *d)
+static void cf_check flask_free_security_domain(struct domain *d)
{
struct domain_security_struct *dsec = d->ssid;
@@ -549,7 +549,7 @@ static int cf_check flask_schedop_shutdo
}
static void cf_check flask_security_domaininfo(
- struct domain *d, struct xen_domctl_getdomaininfo *info)
+ const struct domain *d, struct xen_domctl_getdomaininfo *info)
{
info->ssidref = domain_sid(d);
}
@@ -1904,7 +1904,6 @@ static int cf_check flask_get_domain_sta
static const struct xsm_ops __initconst_cf_clobber flask_ops = {
.set_system_active = flask_set_system_active,
- .security_domaininfo = flask_security_domaininfo,
#define XSM_HOOK0(rtype, name) .name = flask_ ## name,
#define XSM_HOOK1(rtype, name, ...) XSM_HOOK0(rtype, name)
@@ -1915,9 +1914,6 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .alloc_security_domain = flask_domain_alloc_security,
- .free_security_domain = flask_domain_free_security,
-
.show_irq_sid = flask_show_irq_sid,
};
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 13/14] XSM: convert remaining miscellaneous hooks
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (11 preceding siblings ...)
2026-08-17 8:57 ` [PATCH v2 12/14] XSM: convert remaining domain-related hooks Jan Beulich
@ 2026-08-17 8:58 ` Jan Beulich
2026-08-17 8:58 ` [PATCH RFC v2 14/14] XSM: avoid fragile assumptions in xsm_fixup_ops() Jan Beulich
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:58 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org
Cc: Daniel Smith, Julien Grall, Stefano Stabellini, Volodymyr Babchuk,
Bertrand Marquis, Michal Orzel, Andrew Cooper, Teddy Astie,
Roger Pau Monné
Make the ones left also follow the standard scheme, i.e. taking
xsm_default_t as first argument at call sites. This way they can be
covered by the recently introduced hook machinery.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
Interestingly .show_irq_sid() is unused on Arm. Oddly there's no use of
register_keyhandler() there at all. (IOW I think it would be wrong to make
the hook x86-only.)
---
v2: New.
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -497,7 +497,7 @@ void asmlinkage __init noreturn start_xe
/* Hide UART from DOM0 if we're using it */
serial_endboot();
- if ( (rc = xsm_set_system_active()) != 0 )
+ if ( (rc = xsm_set_system_active(XSM_HOOK)) != 0 )
panic("xsm: unable to switch to SYSTEM_ACTIVE privilege: %d\n", rc);
system_state = SYS_STATE_active;
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2549,7 +2549,7 @@ static void cf_check dump_irqs(unsigned
if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type )
continue;
- ssid = in_irq() ? NULL : xsm_show_irq_sid(irq);
+ ssid = in_irq() ? NULL : xsm_show_irq_sid(XSM_HOOK, irq);
spin_lock_irqsave(&desc->lock, flags);
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -835,7 +835,7 @@ static void noreturn init_done(void)
unsigned long start, end;
int err;
- if ( (err = xsm_set_system_active()) != 0 )
+ if ( (err = xsm_set_system_active(XSM_HOOK)) != 0 )
panic("xsm: unable to switch to SYSTEM_ACTIVE privilege: %d\n", err);
system_state = SYS_STATE_active;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -104,10 +104,12 @@ static always_inline int xsm_default_act
}
}
-static XSM_INLINE int xsm_set_system_active(void)
+static XSM_INLINE int xsm_set_system_active(XSM_DEFAULT_VOID)
{
struct domain *d = current->domain;
+ XSM_ASSERT_ACTION(XSM_HOOK);
+
ASSERT(d->is_privileged);
if ( d->domain_id != DOMID_IDLE )
@@ -467,8 +469,9 @@ static XSM_INLINE int xsm_do_compat_op(X
#endif /* CONFIG_XSM */
-static XSM_INLINE char *xsm_show_irq_sid(int irq)
+static XSM_INLINE char *xsm_show_irq_sid(XSM_DEFAULT_ARG int irq)
{
+ XSM_ASSERT_ACTION(XSM_HOOK);
return NULL;
}
--- a/xen/include/xsm/hooks.h
+++ b/xen/include/xsm/hooks.h
@@ -17,6 +17,8 @@
#endif /* XSM_HOOK */
+XSM_HOOK(int, set_system_active)
+
XSM_HOOK(int, domain_create, struct domain *, uint32_t)
XSM_HOOK(int, getdomaininfo, struct domain *)
XSM_HOOK(int, get_domain_state, struct domain *)
@@ -84,6 +86,8 @@ XSM_HOOK(int, irq_mapping, struct domain
XSM_HOOK(int, pt_irq_binding, struct domain *, struct xen_domctl_bind_pt_irq *,
bool)
+XSM_HOOK(pchar_t, show_irq_sid, int)
+
XSM_HOOK(int, irq_permission, struct domain *, int, bool)
XSM_HOOK(int, iomem_permission, struct domain *, uint64_t, uint64_t, bool)
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -61,7 +61,6 @@ typedef enum xsm_default xsm_default_t;
* !!! WARNING !!!
*/
struct xsm_ops {
- int (*set_system_active)(void);
#define XSM_HOOK0(rtype, name) rtype (*name)(void);
#define XSM_HOOK1(rtype, name, type1) \
@@ -77,7 +76,6 @@ struct xsm_ops {
#include "hooks.h"
- char *(*show_irq_sid)(int irq);
};
#ifdef CONFIG_XSM
@@ -86,11 +84,6 @@ extern struct xsm_ops xsm_ops;
#ifndef XSM_NO_WRAPPERS
-static inline int xsm_set_system_active(void)
-{
- return alternative_call(xsm_ops.set_system_active);
-}
-
#define XSM_ALT_void alternative_vcall
#define XSM_ALT_int return alternative_call
#define XSM_ALT_pchar_t return alternative_call
@@ -138,11 +131,6 @@ static inline rtype xsm_ ## name( \
#include "hooks.h"
-static inline char *xsm_show_irq_sid(int irq)
-{
- return alternative_call(xsm_ops.show_irq_sid, irq);
-}
-
#endif /* XSM_NO_WRAPPERS */
#ifdef CONFIG_MULTIBOOT
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -14,7 +14,6 @@
#include <xsm/dummy.h>
static const struct xsm_ops __initconst_cf_clobber dummy_ops = {
- .set_system_active = xsm_set_system_active,
#define XSM_HOOK0(rtype, name) .name = xsm_ ## name,
#define XSM_HOOK1(rtype, name, ...) XSM_HOOK0(rtype, name)
@@ -25,7 +24,6 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .show_irq_sid = xsm_show_irq_sid,
};
void __init xsm_fixup_ops(struct xsm_ops *ops)
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1903,7 +1903,6 @@ static int cf_check flask_get_domain_sta
}
static const struct xsm_ops __initconst_cf_clobber flask_ops = {
- .set_system_active = flask_set_system_active,
#define XSM_HOOK0(rtype, name) .name = flask_ ## name,
#define XSM_HOOK1(rtype, name, ...) XSM_HOOK0(rtype, name)
@@ -1914,7 +1913,6 @@ static const struct xsm_ops __initconst_
#include <xsm/hooks.h>
- .show_irq_sid = flask_show_irq_sid,
};
const struct xsm_ops *__init flask_init(
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH RFC v2 14/14] XSM: avoid fragile assumptions in xsm_fixup_ops()
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
` (12 preceding siblings ...)
2026-08-17 8:58 ` [PATCH v2 13/14] XSM: convert remaining miscellaneous hooks Jan Beulich
@ 2026-08-17 8:58 ` Jan Beulich
13 siblings, 0 replies; 15+ messages in thread
From: Jan Beulich @ 2026-08-17 8:58 UTC (permalink / raw)
To: xen-devel@lists.xenproject.org; +Cc: Daniel Smith, Andrew Cooper
Using the recently introduced hook machinery, the assumptions made can be
avoided, at the expense of a significant code size increase.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
RFC: Of course the significantly increased code size isn't nice. Yet then
it's all .init.text bloat only.
RFC: The asm() is somewhat like RELOC_HIDE(), with an offset of 0. It
didn't feel quite right to use that macro here, though.
The generated code I've looked at (both for x86 and Arm64) it is clear
that a similar weakness in codegen exists for the recurring accesses to
_{s,e}text[] by is_kernel_text(): A register variable each would shrink
code size significantly, yet that doesn't appear to happen at -O1. Yet
open-coding isn't an option, imo.
---
v2: New.
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -51,15 +51,6 @@ typedef enum xsm_default xsm_default_t;
#define XSM_MMU_MACHPHYS_UPDATE 8
#endif /* CONFIG_X86 */
-/*
- * !!! WARNING !!!
- *
- * For simplicity, xsm_fixup_ops() expects that this structure is made
- * exclusively of function pointers to non-init functions. Think carefully
- * before deviating from the pattern.
- *
- * !!! WARNING !!!
- */
struct xsm_ops {
#define XSM_HOOK0(rtype, name) rtype (*name)(void);
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -28,29 +28,35 @@ static const struct xsm_ops __initconst_
void __init xsm_fixup_ops(struct xsm_ops *ops)
{
+ const struct xsm_ops *dops = &dummy_ops;
+
/*
- * We make some simplifying assumptions about struct xsm_ops; that it is
- * made exclusively of function pointers to non-init text.
- *
- * This allows us to walk over struct xsm_ops as if it were an array of
- * unsigned longs.
+ * To limit the size of generated code (by avoiding the compiler using
+ * dummy_ops directly for every access), hide the relationship between
+ * dops and dummy_ops.
*/
- unsigned long *dst = _p(ops);
- const unsigned long *src = _p(&dummy_ops);
+ asm ( "" : "+r" (dops) );
- for ( ; dst < (unsigned long *)(ops + 1); src++, dst++ )
- {
- /*
- * If you encounter this BUG(), then you've most likely added a new
- * XSM hook but failed to provide the default implementation in
- * dummy_ops.
- *
- * If not, then perhaps a function pointer to an init function, or
- * something which isn't a function pointer at all.
- */
- BUG_ON(!is_kernel_text(*src));
+ /*
+ * If you encounter the BUG() below, then you've most likely added a
+ * new XSM hook but failed to provide the default implementation in
+ * dummy_ops.
+ *
+ * If not, then perhaps a function pointer to an init function, or
+ * (less likely) something which isn't a function pointer at all.
+ */
+#define XSM_HOOK0(rtype, name) \
+ do { \
+ typeof(xsm_ ## name) *dummy = dops->name; \
+ BUG_ON(!is_kernel_text(dummy)); \
+ if ( !ops->name ) \
+ ops->name = dummy; \
+ } while ( false );
+#define XSM_HOOK1(rtype, name, ...) XSM_HOOK0(rtype, name)
+#define XSM_HOOK2(rtype, name, ...) XSM_HOOK0(rtype, name)
+#define XSM_HOOK3(rtype, name, ...) XSM_HOOK0(rtype, name)
+#define XSM_HOOK4(rtype, name, ...) XSM_HOOK0(rtype, name)
+#define XSM_HOOK5(rtype, name, ...) XSM_HOOK0(rtype, name)
- if ( !*dst )
- *dst = *src;
- }
+#include <xsm/hooks.h>
}
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-08-17 9:15 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17 8:49 [PATCH v2 00/14] XSM: follow-on to XSAs 492 and 499 Jan Beulich
2026-08-17 8:51 ` [PATCH v2 01/14] XSM: make xsm_default_action() const-correct Jan Beulich
2026-08-17 8:51 ` [PATCH v2 02/14] XSM: convert "allow" (Flask: "access") parameters to bool Jan Beulich
2026-08-17 8:52 ` [PATCH v2 03/14] x86/mm: get_page_from_l1e() is PV-or-shadow-only Jan Beulich
2026-08-17 8:52 ` [PATCH v2 04/14] x86: restrict PHYSDEVOP_* when PV=n Jan Beulich
2026-08-17 8:53 ` [PATCH v2 05/14] XSM: make Argo hooks well-formed ones Jan Beulich
2026-08-17 8:53 ` [PATCH v2 06/14] XSM: fold xsm_{,un}map_domain_pirq() hooks Jan Beulich
2026-08-17 8:54 ` [PATCH v2 07/14] x86: type-correct last parameter of map_domain_pirq() Jan Beulich
2026-08-17 8:54 ` [PATCH v2 08/14] XSM: pass just SBDF to xsm_{,un}map_domain_irq() Jan Beulich
2026-08-17 8:55 ` [PATCH v2 09/14] XSM: fold xsm_{,un}map_domain_irq() hooks Jan Beulich
2026-08-17 8:56 ` [PATCH v2 10/14] XSM: fold xsm_{,un}bind_pt_irq() hooks Jan Beulich
2026-08-17 8:56 ` [PATCH v2 11/14] XSM: convert remaining event channel hooks Jan Beulich
2026-08-17 8:57 ` [PATCH v2 12/14] XSM: convert remaining domain-related hooks Jan Beulich
2026-08-17 8:58 ` [PATCH v2 13/14] XSM: convert remaining miscellaneous hooks Jan Beulich
2026-08-17 8:58 ` [PATCH RFC v2 14/14] XSM: avoid fragile assumptions in xsm_fixup_ops() Jan Beulich
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.