* Xen Security Advisory 237 - multiple MSI mapping issues on x86
@ 2017-10-12 12:16 Xen.org security team
0 siblings, 0 replies; only message in thread
From: Xen.org security team @ 2017-10-12 12:16 UTC (permalink / raw)
To: xen-announce, xen-devel, xen-users, oss-security; +Cc: Xen.org security team
[-- Attachment #1: Type: text/plain, Size: 7059 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Xen Security Advisory XSA-237
version 2
multiple MSI mapping issues on x86
UPDATES IN VERSION 2
====================
Public release.
ISSUE DESCRIPTION
=================
Multiple issues exist with the setup of PCI MSI interrupts:
- - unprivileged guests were permitted access to devices not owned by
them, in particular allowing them to disable MSI or MSI-X on any
device
- - HVM guests can trigger a codepath intended only for PV guests
- - some failure paths partially tear down previously configured
interrupts, leaving inconsistent state
- - with XSM enabled, caller and callee of a hook disagreed about the
data structure pointed to by a type-less argument
IMPACT
======
A malicious or buggy guest may cause the hypervisor to crash, resulting
in Denial of Service (DoS) affecting the entire host. Privilege
escalation and information leaks cannot be excluded.
VULNERABLE SYSTEMS
==================
All Xen versions from at 3.3 onwards are vulnerable. Xen versions 3.2
and earlier are not vulnerable.
Only x86 systems are affected. ARM systems are not affected.
Only guests which have a physical device assigned to them can exploit
the vulnerability.
MITIGATION
==========
Not passing through physical devices to untrusted guests will avoid
the vulnerability.
The vulnerability can be avoided if the guest kernel is controlled by
the host rather than guest administrator, provided that further steps
are taken to prevent the guest administrator from loading code into the
kernel (e.g. by disabling loadable modules etc) or from using other
mechanisms which allow them to run code at kernel privilege.
CREDITS
=======
This issue was discovered by Simon Gaiser of Qubes OS Project.
RESOLUTION
==========
Applying the appropriate attached set of patches resolves this issue.
xsa237-unstable/*.patch xen-unstable
xsa237-4.9/*.patch Xen 4.9.x
xsa237-4.8/*.patch Xen 4.8.x, Xen 4.7.x
xsa237-4.6/*.patch Xen 4.6.x
xsa237-4.5/*.patch Xen 4.5.x
$ sha256sum xsa237* xsa237*/*
1d4d3fa452e91d235fd688761d695752bde2f2e91fd9b17f566c4cee23ae26d0 xsa237.meta
3259cd514ea80e3cbac5b72376b4e964afb3b2cabee347440ec2bdd6e585c513 xsa237-unstable/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
7ef53f6a5f3fc6952cb8411e31e0a670de5a78ab2c8176037db32cf147438aa6 xsa237-unstable/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
494a79332fc5f854f0dc7606669201717a41e5b89b44db2fb30607a326930bfb xsa237-unstable/0003-x86-MSI-disallow-redundant-enabling.patch
503b58512c5336aff9692c0d0768f38ee956c0988fa3fad4d439f13814736e06 xsa237-unstable/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
dc5f27245e44582db682ac53f24007685ea2f8cb104bad9b4d6afeaa7c4e73d2 xsa237-unstable/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
cd9cd248c4564552bbe847462d247b78ff6af1052198e6b6529178a8a624e1f6 xsa237-4.5/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
87bbb240323b3cce9767da73961d58436c436db6da614c62ade7640f87f748dd xsa237-4.5/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
6a2e6772fa7b7a1683f7b1041f06757562622228635aedb8c760ebcd9ad0ff7a xsa237-4.5/0003-x86-MSI-disallow-redundant-enabling.patch
c558ca347b6df9b430fbdaf9c9b8e3b203c273be1e2bb01aa3424773b88df91d xsa237-4.5/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
60169e2016451e1c479c4f873ee6798b6abc46e3223a60a4b83bac20a7a3d27c xsa237-4.5/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
cd9cd248c4564552bbe847462d247b78ff6af1052198e6b6529178a8a624e1f6 xsa237-4.6/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
d39d1c0eaf2ba169b6596520b05930d280721c397fafa3414b6da6168e8b73ca xsa237-4.6/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
494a79332fc5f854f0dc7606669201717a41e5b89b44db2fb30607a326930bfb xsa237-4.6/0003-x86-MSI-disallow-redundant-enabling.patch
c558ca347b6df9b430fbdaf9c9b8e3b203c273be1e2bb01aa3424773b88df91d xsa237-4.6/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
4cdcd71758d9e5b392c38aeafc9960a4f3ef5c109508e69b2218a8d8394edf0b xsa237-4.6/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
1ae6aefb86ba0c48a45ecc14ff56ea0bc3d9d354937668bcacadaed1225017a8 xsa237-4.8/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
bf2ca9cb99ee64d7db77d628cec1a84684c360fd36de433cbc78fbcde8095319 xsa237-4.8/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
494a79332fc5f854f0dc7606669201717a41e5b89b44db2fb30607a326930bfb xsa237-4.8/0003-x86-MSI-disallow-redundant-enabling.patch
9a38899afd728d504382954de28657aa82af7da352eb4e45a5e615bd646834c5 xsa237-4.8/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
fef5c77f19e2c6229912f1fd19cbcb41c1ce554ff53be22198b2f34ea7a27314 xsa237-4.8/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
c97819cdf567c9bb2c38083a941995f836d7dabe3c8bbedf2205e3996cfbce68 xsa237-4.9/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch
d31a2d1053d377e7159060f24a7dbf1d5fd9ebd1f4e4556c4c16b3f409a81130 xsa237-4.9/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch
494a79332fc5f854f0dc7606669201717a41e5b89b44db2fb30607a326930bfb xsa237-4.9/0003-x86-MSI-disallow-redundant-enabling.patch
f8d8c9f70b22d735960393bce042f39caaaf12e42344394e6078461437fa39aa xsa237-4.9/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch
7f3955a8218850ee2cc9ddd9d11fdc25f526d32e80e189d063e3e779d448af40 xsa237-4.9/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch
$
DEPLOYMENT DURING EMBARGO
=========================
Deployment of the patches and/or mitigations described above (or
others which are substantially similar) is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators.
But: Distribution of updated software is prohibited (except to other
members of the predisclosure list).
Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.
(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable. This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)
For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAEBCAAGBQJZ310MAAoJEIP+FMlX6CvZT1AIAJA2DvAtZ3iMEVAPkpCUTibf
9gNGp6osdzFMDP7F2Hwym3Ujm4if2Gr10DeKGAwpDXQhmQ98YSImDY3D11EROVAZ
DkfXScGCImXIf8Kaya4N3bTYydYa9gsraXUZgL9Jcq6/27ihHx/qIbN0q0QPN5TL
AIjaOq7SjhWMubM6+DmjaEsz2KGAE7vXLpkVGQaUhy72InNd2dKqmXnn37lQsi5t
4PEu0CPajb8lQOI2Vu7yhrGGmYMlzJhDs3PuLR4gjIKoxjPtr/MmiAiu2PZXbTKP
mqUmiIXuofbItwuHl1XfJQt+4wFb4rF39b9xulGfQxjTubiRdXTnPiTkdKmNL/E=
=rznL
-----END PGP SIGNATURE-----
[-- Attachment #2: xsa237.meta --]
[-- Type: application/octet-stream, Size: 1702 bytes --]
{
"XSA": 237,
"SupportedVersions": [
"master",
"4.9",
"4.8",
"4.7",
"4.6",
"4.5"
],
"Trees": [
"xen"
],
"Recipes": {
"4.5": {
"XenVersion": "4.5",
"Recipes": {
"xen": {
"StableRef": "83724d9f3ae21a3b96362742e2f052b19d9f559a",
"Prereqs": [],
"Patches": [
"xsa237-4.5/*"
]
}
}
},
"4.6": {
"XenVersion": "4.6",
"Recipes": {
"xen": {
"StableRef": "1658a87690ac839e85db12bbf409be62bb938640",
"Prereqs": [],
"Patches": [
"xsa237-4.6/*"
]
}
}
},
"4.7": {
"XenVersion": "4.7",
"Recipes": {
"xen": {
"StableRef": "c7783d9c26fc191862d9883da22387340b1fab18",
"Prereqs": [],
"Patches": [
"xsa237-4.8/*"
]
}
}
},
"4.8": {
"XenVersion": "4.8",
"Recipes": {
"xen": {
"StableRef": "36898eb12572f0a1f85cb54d4a9e90afcb6f7045",
"Prereqs": [],
"Patches": [
"xsa237-4.8/*"
]
}
}
},
"4.9": {
"XenVersion": "4.9",
"Recipes": {
"xen": {
"StableRef": "2cc3d32f40c71cb242477a3f8938074d4fc36829",
"Prereqs": [],
"Patches": [
"xsa237-4.9/*"
]
}
}
},
"master": {
"XenVersion": "master",
"Recipes": {
"xen": {
"StableRef": "a8ea6e2688118a3e19e29b39e316faa5f96ab9d1",
"Prereqs": [],
"Patches": [
"xsa237-unstable/*"
]
}
}
}
}
}
[-- Attachment #3: xsa237-unstable/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch --]
[-- Type: application/octet-stream, Size: 843 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't allow MSI pIRQ mapping on unowned device
MSI setup should be permitted only for existing devices owned by the
respective guest (the operation may still be carried out by the domain
controlling that guest).
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1967,7 +1967,10 @@ int map_domain_pirq(
if ( !cpu_has_apic )
goto done;
- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
+ if ( !pdev )
+ goto done;
+
ret = pci_enable_msi(msi, &msi_desc);
if ( ret )
{
[-- Attachment #4: xsa237-unstable/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch --]
[-- Type: application/octet-stream, Size: 2177 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
This in turn requires bypassing the XSM check in physdev_unmap_pirq()
for the HVM emuirq case just like is being done in physdev_map_pirq().
The primary goal security wise, however, is to no longer allow HVM
guests, by specifying their own domain ID instead of DOMID_SELF, to
enter code paths intended for PV guest and the control domains of HVM
guests only.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
if ( d == NULL )
return -ESRCH;
- ret = xsm_map_domain_pirq(XSM_TARGET, d);
+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
@@ -144,13 +144,14 @@ int physdev_map_pirq(domid_t domid, int
int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
- int ret;
+ int ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
return -ESRCH;
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
+ if ( domid != DOMID_SELF || !is_hvm_domain(d) || !has_pirq(d) )
+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -441,7 +441,7 @@ static XSM_INLINE char *xsm_show_irq_sid
static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -453,7 +453,7 @@ static XSM_INLINE int xsm_map_domain_irq
static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
[-- Attachment #5: xsa237-unstable/0003-x86-MSI-disallow-redundant-enabling.patch --]
[-- Type: application/octet-stream, Size: 2156 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/MSI: disallow redundant enabling
At the moment, Xen attempts to allow redundant enabling of MSI by
having pci_enable_msi() return 0, and point to the existing MSI
descriptor, when the msi already exists.
Unfortunately, if subsequent errors are encountered, the cleanup
paths assume pci_enable_msi() had done full initialization, and
hence undo everything that was assumed to be done by that
function without also undoing other setup that would normally
occur only after that function was called (in map_domain_pirq()
itself).
Rather than try to make the redundant enabling case work properly, just
forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
is already set up.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
[-- Attachment #6: xsa237-unstable/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch --]
[-- Type: application/octet-stream, Size: 3725 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
Mappings that had been set up before should not be torn down when
handling unrelated errors.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1254,7 +1254,8 @@ static int prepare_domain_irq_pirq(struc
return -ENOMEM;
}
*pinfo = info;
- return 0;
+
+ return !!err;
}
static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
@@ -1297,7 +1298,10 @@ int init_domain_irq_mapping(struct domai
continue;
err = prepare_domain_irq_pirq(d, i, i, &info);
if ( err )
+ {
+ ASSERT(err < 0);
break;
+ }
set_domain_irq_pirq(d, i, info);
}
@@ -1898,6 +1902,8 @@ int get_free_pirqs(struct domain *d, uns
return -ENOSPC;
}
+#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)
{
@@ -1906,6 +1912,7 @@ int map_domain_pirq(
struct pirq *info;
struct irq_desc *desc;
unsigned long flags;
+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
ASSERT(spin_is_locked(&d->event_lock));
@@ -1949,8 +1956,10 @@ int map_domain_pirq(
}
ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
- if ( ret )
+ if ( ret < 0 )
goto revoke;
+ if ( !ret )
+ __set_bit(0, prepared);
desc = irq_to_desc(irq);
@@ -2022,8 +2031,10 @@ int map_domain_pirq(
irq = create_irq(NUMA_NO_NODE);
ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
: irq;
- if ( ret )
+ if ( ret < 0 )
break;
+ if ( !ret )
+ __set_bit(nr, prepared);
msi_desc[nr].irq = irq;
if ( irq_permit_access(d, irq) != 0 )
@@ -2056,15 +2067,15 @@ int map_domain_pirq(
desc->msi_desc = NULL;
spin_unlock_irqrestore(&desc->lock, flags);
}
- while ( nr-- )
+ while ( nr )
{
if ( irq >= 0 && irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
"dom%d: could not revoke access to IRQ%d (pirq %d)\n",
d->domain_id, irq, pirq);
- if ( info )
+ if ( info && test_bit(nr, prepared) )
cleanup_domain_irq_pirq(d, irq, info);
- info = pirq_info(d, pirq + nr);
+ info = pirq_info(d, pirq + --nr);
irq = info->arch.irq;
}
msi_desc->irq = -1;
@@ -2080,12 +2091,14 @@ int map_domain_pirq(
spin_lock_irqsave(&desc->lock, flags);
set_domain_irq_pirq(d, irq, info);
spin_unlock_irqrestore(&desc->lock, flags);
+ ret = 0;
}
done:
if ( ret )
{
- cleanup_domain_irq_pirq(d, irq, info);
+ if ( test_bit(0, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
revoke:
if ( irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
@@ -2560,7 +2573,7 @@ static int allocate_pirq(struct domain *
}
else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- if ( *nr <= 0 || *nr > 32 )
+ if ( *nr <= 0 || *nr > MAX_MSI_IRQS )
return -EDOM;
if ( *nr != 1 && !iommu_intremap )
return -EOPNOTSUPP;
[-- Attachment #7: xsa237-unstable/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch --]
[-- Type: application/octet-stream, Size: 1273 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
The caller and the FLASK implementation of xsm_unmap_domain_irq()
disagreed about what the "data" argument points to in the MSI case:
Change both sides to pass/take a PCI device.
This is part of XSA-237.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2149,7 +2149,8 @@ int unmap_domain_pirq(struct domain *d,
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
if ( ret )
goto done;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -918,8 +918,8 @@ static int flask_unmap_domain_msi (struc
u32 *sid, struct avc_audit_data *ad)
{
#ifdef CONFIG_HAS_PCI
- struct msi_info *msi = data;
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ const struct pci_dev *pdev = data;
+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
AVC_AUDIT_DATA_INIT(ad, DEV);
ad->device = machine_bdf;
[-- Attachment #8: xsa237-4.5/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch --]
[-- Type: application/octet-stream, Size: 843 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't allow MSI pIRQ mapping on unowned device
MSI setup should be permitted only for existing devices owned by the
respective guest (the operation may still be carried out by the domain
controlling that guest).
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1961,7 +1961,10 @@ int map_domain_pirq(
if ( !cpu_has_apic )
goto done;
- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
+ if ( !pdev )
+ goto done;
+
ret = pci_enable_msi(msi, &msi_desc);
if ( ret )
{
[-- Attachment #9: xsa237-4.5/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch --]
[-- Type: application/octet-stream, Size: 2161 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
This in turn requires bypassing the XSM check in physdev_unmap_pirq()
for the HVM emuirq case just like is being done in physdev_map_pirq().
The primary goal security wise, however, is to no longer allow HVM
guests, by specifying their own domain ID instead of DOMID_SELF, to
enter code paths intended for PV guest and the control domains of HVM
guests only.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
if ( d == NULL )
return -ESRCH;
- ret = xsm_map_domain_pirq(XSM_TARGET, d);
+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
@@ -255,13 +255,14 @@ int physdev_map_pirq(domid_t domid, int
int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
- int ret;
+ int ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
return -ESRCH;
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
+ if ( domid != DOMID_SELF || !is_hvm_domain(d) )
+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -429,7 +429,7 @@ static XSM_INLINE char *xsm_show_irq_sid
static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -441,7 +441,7 @@ static XSM_INLINE int xsm_map_domain_irq
static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
[-- Attachment #10: xsa237-4.5/0003-x86-MSI-disallow-redundant-enabling.patch --]
[-- Type: application/octet-stream, Size: 2439 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/MSI: disallow redundant enabling
At the moment, Xen attempts to allow redundant enabling of MSI by
having pci_enable_msi() return 0, and point to the existing MSI
descriptor, when the msi already exists.
Unfortunately, if subsequent errors are encountered, the cleanup
paths assume pci_enable_msi() had done full initialization, and
hence undo everything that was assumed to be done by that
function without also undoing other setup that would normally
occur only after that function was called (in map_domain_pirq()
itself).
Rather than try to make the redundant enabling case work properly, just
forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
is already set up.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -886,12 +886,10 @@ static int __pci_enable_msi(struct msi_i
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
if ( old_desc )
{
- dprintk(XENLOG_WARNING, "irq %d has already mapped to MSI on "
- "device %04x:%02x:%02x.%01x\n",
- msi->irq, msi->seg, msi->bus,
- PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ msi->irq, msi->seg, msi->bus,
+ PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
@@ -956,12 +954,10 @@ static int __pci_enable_msix(struct msi_
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
if ( old_desc )
{
- dprintk(XENLOG_WARNING, "irq %d has already mapped to MSIX on "
- "device %04x:%02x:%02x.%01x\n",
- msi->irq, msi->seg, msi->bus,
- PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ msi->irq, msi->seg, msi->bus,
+ PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
[-- Attachment #11: xsa237-4.5/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch --]
[-- Type: application/octet-stream, Size: 3887 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
Mappings that had been set up before should not be torn down when
handling unrelated errors.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1249,7 +1249,8 @@ static int prepare_domain_irq_pirq(struc
return -ENOMEM;
}
*pinfo = info;
- return 0;
+
+ return !!err;
}
static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
@@ -1292,7 +1293,10 @@ int init_domain_irq_mapping(struct domai
continue;
err = prepare_domain_irq_pirq(d, i, i, &info);
if ( err )
+ {
+ ASSERT(err < 0);
break;
+ }
set_domain_irq_pirq(d, i, info);
}
@@ -1900,6 +1904,7 @@ int map_domain_pirq(
struct pirq *info;
struct irq_desc *desc;
unsigned long flags;
+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
ASSERT(spin_is_locked(&d->event_lock));
@@ -1943,8 +1948,10 @@ int map_domain_pirq(
}
ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
- if ( ret )
+ if ( ret < 0 )
goto revoke;
+ if ( !ret )
+ __set_bit(0, prepared);
desc = irq_to_desc(irq);
@@ -2016,8 +2023,10 @@ int map_domain_pirq(
irq = create_irq(NUMA_NO_NODE);
ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
: irq;
- if ( ret )
+ if ( ret < 0 )
break;
+ if ( !ret )
+ __set_bit(nr, prepared);
msi_desc[nr].irq = irq;
if ( irq_permit_access(d, irq) != 0 )
@@ -2050,15 +2059,15 @@ int map_domain_pirq(
desc->msi_desc = NULL;
spin_unlock_irqrestore(&desc->lock, flags);
}
- while ( nr-- )
+ while ( nr )
{
if ( irq >= 0 && irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
"dom%d: could not revoke access to IRQ%d (pirq %d)\n",
d->domain_id, irq, pirq);
- if ( info )
+ if ( info && test_bit(nr, prepared) )
cleanup_domain_irq_pirq(d, irq, info);
- info = pirq_info(d, pirq + nr);
+ info = pirq_info(d, pirq + --nr);
irq = info->arch.irq;
}
msi_desc->irq = -1;
@@ -2074,12 +2083,14 @@ int map_domain_pirq(
spin_lock_irqsave(&desc->lock, flags);
set_domain_irq_pirq(d, irq, info);
spin_unlock_irqrestore(&desc->lock, flags);
+ ret = 0;
}
done:
if ( ret )
{
- cleanup_domain_irq_pirq(d, irq, info);
+ if ( test_bit(0, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
revoke:
if ( irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -185,7 +185,7 @@ int physdev_map_pirq(domid_t domid, int
}
else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
+ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
ret = -EDOM;
else if ( msi->entry_nr != 1 && !iommu_intremap )
ret = -EOPNOTSUPP;
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -55,6 +55,8 @@
/* MAX fixed pages reserved for mapping MSIX tables. */
#define FIX_MSIX_MAX_PAGES 512
+#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
+
struct msi_info {
u16 seg;
u8 bus;
[-- Attachment #12: xsa237-4.5/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch --]
[-- Type: application/octet-stream, Size: 1266 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
The caller and the FLASK implementation of xsm_unmap_domain_irq()
disagreed about what the "data" argument points to in the MSI case:
Change both sides to pass/take a PCI device.
This is part of XSA-237.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2141,7 +2141,8 @@ int unmap_domain_pirq(struct domain *d,
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
if ( ret )
goto done;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -884,8 +884,8 @@ static int flask_unmap_domain_msi (struc
u32 *sid, struct avc_audit_data *ad)
{
#ifdef HAS_PCI
- struct msi_info *msi = data;
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ const struct pci_dev *pdev = data;
+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
AVC_AUDIT_DATA_INIT(ad, DEV);
ad->device = machine_bdf;
[-- Attachment #13: xsa237-4.6/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch --]
[-- Type: application/octet-stream, Size: 843 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't allow MSI pIRQ mapping on unowned device
MSI setup should be permitted only for existing devices owned by the
respective guest (the operation may still be carried out by the domain
controlling that guest).
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1961,7 +1961,10 @@ int map_domain_pirq(
if ( !cpu_has_apic )
goto done;
- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
+ if ( !pdev )
+ goto done;
+
ret = pci_enable_msi(msi, &msi_desc);
if ( ret )
{
[-- Attachment #14: xsa237-4.6/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch --]
[-- Type: application/octet-stream, Size: 2161 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
This in turn requires bypassing the XSM check in physdev_unmap_pirq()
for the HVM emuirq case just like is being done in physdev_map_pirq().
The primary goal security wise, however, is to no longer allow HVM
guests, by specifying their own domain ID instead of DOMID_SELF, to
enter code paths intended for PV guest and the control domains of HVM
guests only.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
if ( d == NULL )
return -ESRCH;
- ret = xsm_map_domain_pirq(XSM_TARGET, d);
+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
@@ -255,13 +255,14 @@ int physdev_map_pirq(domid_t domid, int
int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
- int ret;
+ int ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
return -ESRCH;
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
+ if ( domid != DOMID_SELF || !is_hvm_domain(d) )
+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -446,7 +446,7 @@ static XSM_INLINE char *xsm_show_irq_sid
static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -458,7 +458,7 @@ static XSM_INLINE int xsm_map_domain_irq
static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
[-- Attachment #15: xsa237-4.6/0003-x86-MSI-disallow-redundant-enabling.patch --]
[-- Type: application/octet-stream, Size: 2156 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/MSI: disallow redundant enabling
At the moment, Xen attempts to allow redundant enabling of MSI by
having pci_enable_msi() return 0, and point to the existing MSI
descriptor, when the msi already exists.
Unfortunately, if subsequent errors are encountered, the cleanup
paths assume pci_enable_msi() had done full initialization, and
hence undo everything that was assumed to be done by that
function without also undoing other setup that would normally
occur only after that function was called (in map_domain_pirq()
itself).
Rather than try to make the redundant enabling case work properly, just
forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
is already set up.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
[-- Attachment #16: xsa237-4.6/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch --]
[-- Type: application/octet-stream, Size: 3887 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
Mappings that had been set up before should not be torn down when
handling unrelated errors.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1249,7 +1249,8 @@ static int prepare_domain_irq_pirq(struc
return -ENOMEM;
}
*pinfo = info;
- return 0;
+
+ return !!err;
}
static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
@@ -1292,7 +1293,10 @@ int init_domain_irq_mapping(struct domai
continue;
err = prepare_domain_irq_pirq(d, i, i, &info);
if ( err )
+ {
+ ASSERT(err < 0);
break;
+ }
set_domain_irq_pirq(d, i, info);
}
@@ -1900,6 +1904,7 @@ int map_domain_pirq(
struct pirq *info;
struct irq_desc *desc;
unsigned long flags;
+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
ASSERT(spin_is_locked(&d->event_lock));
@@ -1943,8 +1948,10 @@ int map_domain_pirq(
}
ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
- if ( ret )
+ if ( ret < 0 )
goto revoke;
+ if ( !ret )
+ __set_bit(0, prepared);
desc = irq_to_desc(irq);
@@ -2016,8 +2023,10 @@ int map_domain_pirq(
irq = create_irq(NUMA_NO_NODE);
ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
: irq;
- if ( ret )
+ if ( ret < 0 )
break;
+ if ( !ret )
+ __set_bit(nr, prepared);
msi_desc[nr].irq = irq;
if ( irq_permit_access(d, irq) != 0 )
@@ -2050,15 +2059,15 @@ int map_domain_pirq(
desc->msi_desc = NULL;
spin_unlock_irqrestore(&desc->lock, flags);
}
- while ( nr-- )
+ while ( nr )
{
if ( irq >= 0 && irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
"dom%d: could not revoke access to IRQ%d (pirq %d)\n",
d->domain_id, irq, pirq);
- if ( info )
+ if ( info && test_bit(nr, prepared) )
cleanup_domain_irq_pirq(d, irq, info);
- info = pirq_info(d, pirq + nr);
+ info = pirq_info(d, pirq + --nr);
irq = info->arch.irq;
}
msi_desc->irq = -1;
@@ -2074,12 +2083,14 @@ int map_domain_pirq(
spin_lock_irqsave(&desc->lock, flags);
set_domain_irq_pirq(d, irq, info);
spin_unlock_irqrestore(&desc->lock, flags);
+ ret = 0;
}
done:
if ( ret )
{
- cleanup_domain_irq_pirq(d, irq, info);
+ if ( test_bit(0, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
revoke:
if ( irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -185,7 +185,7 @@ int physdev_map_pirq(domid_t domid, int
}
else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
+ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
ret = -EDOM;
else if ( msi->entry_nr != 1 && !iommu_intremap )
ret = -EOPNOTSUPP;
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -55,6 +55,8 @@
/* MAX fixed pages reserved for mapping MSIX tables. */
#define FIX_MSIX_MAX_PAGES 512
+#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
+
struct msi_info {
u16 seg;
u8 bus;
[-- Attachment #17: xsa237-4.6/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch --]
[-- Type: application/octet-stream, Size: 1266 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
The caller and the FLASK implementation of xsm_unmap_domain_irq()
disagreed about what the "data" argument points to in the MSI case:
Change both sides to pass/take a PCI device.
This is part of XSA-237.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2141,7 +2141,8 @@ int unmap_domain_pirq(struct domain *d,
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
if ( ret )
goto done;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -897,8 +897,8 @@ static int flask_unmap_domain_msi (struc
u32 *sid, struct avc_audit_data *ad)
{
#ifdef HAS_PCI
- struct msi_info *msi = data;
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ const struct pci_dev *pdev = data;
+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
AVC_AUDIT_DATA_INIT(ad, DEV);
ad->device = machine_bdf;
[-- Attachment #18: xsa237-4.8/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch --]
[-- Type: application/octet-stream, Size: 843 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't allow MSI pIRQ mapping on unowned device
MSI setup should be permitted only for existing devices owned by the
respective guest (the operation may still be carried out by the domain
controlling that guest).
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1964,7 +1964,10 @@ int map_domain_pirq(
if ( !cpu_has_apic )
goto done;
- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
+ if ( !pdev )
+ goto done;
+
ret = pci_enable_msi(msi, &msi_desc);
if ( ret )
{
[-- Attachment #19: xsa237-4.8/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch --]
[-- Type: application/octet-stream, Size: 2161 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
This in turn requires bypassing the XSM check in physdev_unmap_pirq()
for the HVM emuirq case just like is being done in physdev_map_pirq().
The primary goal security wise, however, is to no longer allow HVM
guests, by specifying their own domain ID instead of DOMID_SELF, to
enter code paths intended for PV guest and the control domains of HVM
guests only.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int
if ( d == NULL )
return -ESRCH;
- ret = xsm_map_domain_pirq(XSM_TARGET, d);
+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
@@ -255,13 +255,14 @@ int physdev_map_pirq(domid_t domid, int
int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
- int ret;
+ int ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
return -ESRCH;
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
+ if ( domid != DOMID_SELF || !is_hvm_domain(d) )
+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -453,7 +453,7 @@ static XSM_INLINE char *xsm_show_irq_sid
static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -465,7 +465,7 @@ static XSM_INLINE int xsm_map_domain_irq
static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
[-- Attachment #20: xsa237-4.8/0003-x86-MSI-disallow-redundant-enabling.patch --]
[-- Type: application/octet-stream, Size: 2156 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/MSI: disallow redundant enabling
At the moment, Xen attempts to allow redundant enabling of MSI by
having pci_enable_msi() return 0, and point to the existing MSI
descriptor, when the msi already exists.
Unfortunately, if subsequent errors are encountered, the cleanup
paths assume pci_enable_msi() had done full initialization, and
hence undo everything that was assumed to be done by that
function without also undoing other setup that would normally
occur only after that function was called (in map_domain_pirq()
itself).
Rather than try to make the redundant enabling case work properly, just
forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
is already set up.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
[-- Attachment #21: xsa237-4.8/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch --]
[-- Type: application/octet-stream, Size: 3887 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
Mappings that had been set up before should not be torn down when
handling unrelated errors.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1252,7 +1252,8 @@ static int prepare_domain_irq_pirq(struc
return -ENOMEM;
}
*pinfo = info;
- return 0;
+
+ return !!err;
}
static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
@@ -1295,7 +1296,10 @@ int init_domain_irq_mapping(struct domai
continue;
err = prepare_domain_irq_pirq(d, i, i, &info);
if ( err )
+ {
+ ASSERT(err < 0);
break;
+ }
set_domain_irq_pirq(d, i, info);
}
@@ -1903,6 +1907,7 @@ int map_domain_pirq(
struct pirq *info;
struct irq_desc *desc;
unsigned long flags;
+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
ASSERT(spin_is_locked(&d->event_lock));
@@ -1946,8 +1951,10 @@ int map_domain_pirq(
}
ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
- if ( ret )
+ if ( ret < 0 )
goto revoke;
+ if ( !ret )
+ __set_bit(0, prepared);
desc = irq_to_desc(irq);
@@ -2019,8 +2026,10 @@ int map_domain_pirq(
irq = create_irq(NUMA_NO_NODE);
ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
: irq;
- if ( ret )
+ if ( ret < 0 )
break;
+ if ( !ret )
+ __set_bit(nr, prepared);
msi_desc[nr].irq = irq;
if ( irq_permit_access(d, irq) != 0 )
@@ -2053,15 +2062,15 @@ int map_domain_pirq(
desc->msi_desc = NULL;
spin_unlock_irqrestore(&desc->lock, flags);
}
- while ( nr-- )
+ while ( nr )
{
if ( irq >= 0 && irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
"dom%d: could not revoke access to IRQ%d (pirq %d)\n",
d->domain_id, irq, pirq);
- if ( info )
+ if ( info && test_bit(nr, prepared) )
cleanup_domain_irq_pirq(d, irq, info);
- info = pirq_info(d, pirq + nr);
+ info = pirq_info(d, pirq + --nr);
irq = info->arch.irq;
}
msi_desc->irq = -1;
@@ -2077,12 +2086,14 @@ int map_domain_pirq(
spin_lock_irqsave(&desc->lock, flags);
set_domain_irq_pirq(d, irq, info);
spin_unlock_irqrestore(&desc->lock, flags);
+ ret = 0;
}
done:
if ( ret )
{
- cleanup_domain_irq_pirq(d, irq, info);
+ if ( test_bit(0, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
revoke:
if ( irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -185,7 +185,7 @@ int physdev_map_pirq(domid_t domid, int
}
else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
+ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
ret = -EDOM;
else if ( msi->entry_nr != 1 && !iommu_intremap )
ret = -EOPNOTSUPP;
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -55,6 +55,8 @@
/* MAX fixed pages reserved for mapping MSIX tables. */
#define FIX_MSIX_MAX_PAGES 512
+#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
+
struct msi_info {
u16 seg;
u8 bus;
[-- Attachment #22: xsa237-4.8/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch --]
[-- Type: application/octet-stream, Size: 1273 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
The caller and the FLASK implementation of xsm_unmap_domain_irq()
disagreed about what the "data" argument points to in the MSI case:
Change both sides to pass/take a PCI device.
This is part of XSA-237.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2144,7 +2144,8 @@ int unmap_domain_pirq(struct domain *d,
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
if ( ret )
goto done;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -915,8 +915,8 @@ static int flask_unmap_domain_msi (struc
u32 *sid, struct avc_audit_data *ad)
{
#ifdef CONFIG_HAS_PCI
- struct msi_info *msi = data;
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ const struct pci_dev *pdev = data;
+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
AVC_AUDIT_DATA_INIT(ad, DEV);
ad->device = machine_bdf;
[-- Attachment #23: xsa237-4.9/0001-x86-dont-allow-MSI-pIRQ-mapping-on-unowned-device.patch --]
[-- Type: application/octet-stream, Size: 843 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: don't allow MSI pIRQ mapping on unowned device
MSI setup should be permitted only for existing devices owned by the
respective guest (the operation may still be carried out by the domain
controlling that guest).
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1963,7 +1963,10 @@ int map_domain_pirq(
if ( !cpu_has_apic )
goto done;
- pdev = pci_get_pdev(msi->seg, msi->bus, msi->devfn);
+ pdev = pci_get_pdev_by_domain(d, msi->seg, msi->bus, msi->devfn);
+ if ( !pdev )
+ goto done;
+
ret = pci_enable_msi(msi, &msi_desc);
if ( ret )
{
[-- Attachment #24: xsa237-4.9/0002-x86-enforce-proper-privilege-when-mapping-pIRQ-s.patch --]
[-- Type: application/octet-stream, Size: 2177 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86: enforce proper privilege when (un)mapping pIRQ-s
(Un)mapping of IRQs, just like other RESOURCE__ADD* / RESOURCE__REMOVE*
actions (in FLASK terms) should be XSM_DM_PRIV rather than XSM_TARGET.
This in turn requires bypassing the XSM check in physdev_unmap_pirq()
for the HVM emuirq case just like is being done in physdev_map_pirq().
The primary goal security wise, however, is to no longer allow HVM
guests, by specifying their own domain ID instead of DOMID_SELF, to
enter code paths intended for PV guest and the control domains of HVM
guests only.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -111,7 +111,7 @@ int physdev_map_pirq(domid_t domid, int
if ( d == NULL )
return -ESRCH;
- ret = xsm_map_domain_pirq(XSM_TARGET, d);
+ ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
@@ -256,13 +256,14 @@ int physdev_map_pirq(domid_t domid, int
int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
- int ret;
+ int ret = 0;
d = rcu_lock_domain_by_any_id(domid);
if ( d == NULL )
return -ESRCH;
- ret = xsm_unmap_domain_pirq(XSM_TARGET, d);
+ if ( domid != DOMID_SELF || !is_hvm_domain(d) || !has_pirq(d) )
+ ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
if ( ret )
goto free_domain;
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -453,7 +453,7 @@ static XSM_INLINE char *xsm_show_irq_sid
static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
@@ -465,7 +465,7 @@ static XSM_INLINE int xsm_map_domain_irq
static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
{
- XSM_ASSERT_ACTION(XSM_TARGET);
+ XSM_ASSERT_ACTION(XSM_DM_PRIV);
return xsm_default_action(action, current->domain, d);
}
[-- Attachment #25: xsa237-4.9/0003-x86-MSI-disallow-redundant-enabling.patch --]
[-- Type: application/octet-stream, Size: 2156 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/MSI: disallow redundant enabling
At the moment, Xen attempts to allow redundant enabling of MSI by
having pci_enable_msi() return 0, and point to the existing MSI
descriptor, when the msi already exists.
Unfortunately, if subsequent errors are encountered, the cleanup
paths assume pci_enable_msi() had done full initialization, and
hence undo everything that was assumed to be done by that
function without also undoing other setup that would normally
occur only after that function was called (in map_domain_pirq()
itself).
Rather than try to make the redundant enabling case work properly, just
forbid it entirely by having pci_enable_msi() return -EEXIST when MSI
is already set up.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1050,11 +1050,10 @@ static int __pci_enable_msi(struct msi_i
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSI);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSIX);
@@ -1118,11 +1117,10 @@ static int __pci_enable_msix(struct msi_
old_desc = find_msi_entry(pdev, msi->irq, PCI_CAP_ID_MSIX);
if ( old_desc )
{
- printk(XENLOG_WARNING "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
+ printk(XENLOG_ERR "irq %d already mapped to MSI-X on %04x:%02x:%02x.%u\n",
msi->irq, msi->seg, msi->bus,
PCI_SLOT(msi->devfn), PCI_FUNC(msi->devfn));
- *desc = old_desc;
- return 0;
+ return -EEXIST;
}
old_desc = find_msi_entry(pdev, -1, PCI_CAP_ID_MSI);
[-- Attachment #26: xsa237-4.9/0004-x86-IRQ-conditionally-preserve-irq-pirq-mapping-on-error.patch --]
[-- Type: application/octet-stream, Size: 3887 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/IRQ: conditionally preserve irq <-> pirq mapping on map error paths
Mappings that had been set up before should not be torn down when
handling unrelated errors.
This is part of XSA-237.
Reported-by: HW42 <hw42@ipsumj.de>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -1251,7 +1251,8 @@ static int prepare_domain_irq_pirq(struc
return -ENOMEM;
}
*pinfo = info;
- return 0;
+
+ return !!err;
}
static void set_domain_irq_pirq(struct domain *d, int irq, struct pirq *pirq)
@@ -1294,7 +1295,10 @@ int init_domain_irq_mapping(struct domai
continue;
err = prepare_domain_irq_pirq(d, i, i, &info);
if ( err )
+ {
+ ASSERT(err < 0);
break;
+ }
set_domain_irq_pirq(d, i, info);
}
@@ -1902,6 +1906,7 @@ int map_domain_pirq(
struct pirq *info;
struct irq_desc *desc;
unsigned long flags;
+ DECLARE_BITMAP(prepared, MAX_MSI_IRQS) = {};
ASSERT(spin_is_locked(&d->event_lock));
@@ -1945,8 +1950,10 @@ int map_domain_pirq(
}
ret = prepare_domain_irq_pirq(d, irq, pirq, &info);
- if ( ret )
+ if ( ret < 0 )
goto revoke;
+ if ( !ret )
+ __set_bit(0, prepared);
desc = irq_to_desc(irq);
@@ -2018,8 +2025,10 @@ int map_domain_pirq(
irq = create_irq(NUMA_NO_NODE);
ret = irq >= 0 ? prepare_domain_irq_pirq(d, irq, pirq + nr, &info)
: irq;
- if ( ret )
+ if ( ret < 0 )
break;
+ if ( !ret )
+ __set_bit(nr, prepared);
msi_desc[nr].irq = irq;
if ( irq_permit_access(d, irq) != 0 )
@@ -2052,15 +2061,15 @@ int map_domain_pirq(
desc->msi_desc = NULL;
spin_unlock_irqrestore(&desc->lock, flags);
}
- while ( nr-- )
+ while ( nr )
{
if ( irq >= 0 && irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
"dom%d: could not revoke access to IRQ%d (pirq %d)\n",
d->domain_id, irq, pirq);
- if ( info )
+ if ( info && test_bit(nr, prepared) )
cleanup_domain_irq_pirq(d, irq, info);
- info = pirq_info(d, pirq + nr);
+ info = pirq_info(d, pirq + --nr);
irq = info->arch.irq;
}
msi_desc->irq = -1;
@@ -2076,12 +2085,14 @@ int map_domain_pirq(
spin_lock_irqsave(&desc->lock, flags);
set_domain_irq_pirq(d, irq, info);
spin_unlock_irqrestore(&desc->lock, flags);
+ ret = 0;
}
done:
if ( ret )
{
- cleanup_domain_irq_pirq(d, irq, info);
+ if ( test_bit(0, prepared) )
+ cleanup_domain_irq_pirq(d, irq, info);
revoke:
if ( irq_deny_access(d, irq) )
printk(XENLOG_G_ERR
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -186,7 +186,7 @@ int physdev_map_pirq(domid_t domid, int
}
else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
{
- if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
+ if ( msi->entry_nr <= 0 || msi->entry_nr > MAX_MSI_IRQS )
ret = -EDOM;
else if ( msi->entry_nr != 1 && !iommu_intremap )
ret = -EOPNOTSUPP;
--- a/xen/include/asm-x86/msi.h
+++ b/xen/include/asm-x86/msi.h
@@ -56,6 +56,8 @@
/* MAX fixed pages reserved for mapping MSIX tables. */
#define FIX_MSIX_MAX_PAGES 512
+#define MAX_MSI_IRQS 32 /* limited by MSI capability struct properties */
+
struct msi_info {
u16 seg;
u8 bus;
[-- Attachment #27: xsa237-4.9/0005-x86-FLASK-fix-unmap-domain-IRQ-XSM-hook.patch --]
[-- Type: application/octet-stream, Size: 1273 bytes --]
From: Jan Beulich <jbeulich@suse.com>
Subject: x86/FLASK: fix unmap-domain-IRQ XSM hook
The caller and the FLASK implementation of xsm_unmap_domain_irq()
disagreed about what the "data" argument points to in the MSI case:
Change both sides to pass/take a PCI device.
This is part of XSA-237.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2143,7 +2143,8 @@ int unmap_domain_pirq(struct domain *d,
nr = msi_desc->msi.nvec;
}
- ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq, msi_desc);
+ ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+ msi_desc ? msi_desc->dev : NULL);
if ( ret )
goto done;
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -918,8 +918,8 @@ static int flask_unmap_domain_msi (struc
u32 *sid, struct avc_audit_data *ad)
{
#ifdef CONFIG_HAS_PCI
- struct msi_info *msi = data;
- u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn;
+ const struct pci_dev *pdev = data;
+ u32 machine_bdf = (pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn;
AVC_AUDIT_DATA_INIT(ad, DEV);
ad->device = machine_bdf;
[-- Attachment #28: Type: text/plain, Size: 127 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2017-10-12 12:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-12 12:16 Xen Security Advisory 237 - multiple MSI mapping issues on x86 Xen.org security team
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).