aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86
diff options
context:
space:
mode:
authorDaniel De Graaf <dgdegra@tycho.nsa.gov>2011-12-02 13:47:08 -0800
committerDaniel De Graaf <dgdegra@tycho.nsa.gov>2011-12-02 13:47:08 -0800
commit3d7895b3bbe977e3abd2d4128e42c1daba5e3fa4 (patch)
tree3a17a23357b787f377dc3dc669824cc88e352306 /xen/arch/x86
parent65d744c6d56f92401b9d279c9cf8fe618397be0e (diff)
downloadxen-3d7895b3bbe977e3abd2d4128e42c1daba5e3fa4.tar.gz
xen-3d7895b3bbe977e3abd2d4128e42c1daba5e3fa4.tar.bz2
xen-3d7895b3bbe977e3abd2d4128e42c1daba5e3fa4.zip
xsm: Expand I/O resource hooks
The XSM hooks inside rangeset are not useful in capturing the PIRQ mappings in HVM domains. They can also be called from softirq context where current->domain is invalid, causing spurious AVC denials from unrelated domains on such calls. Within FLASK code, the rangeset hooks were already divided between IRQs, I/O memory, and x86 IO ports; propagate this division back through the XSM hooks and call the XSM functions directly when needed. This removes XSM checks for the initial rangeset population for dom0 and the removal checks on domain destruction; denying either of these actions does not make sense. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> Committed-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86')
-rw-r--r--xen/arch/x86/domctl.c24
-rw-r--r--xen/arch/x86/irq.c9
-rw-r--r--xen/arch/x86/physdev.c4
3 files changed, 33 insertions, 4 deletions
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 330b395110..4e258f39ce 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -76,6 +76,7 @@ long arch_do_domctl(
struct domain *d;
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;
ret = -EINVAL;
if ( (fp + np) > 65536 )
@@ -87,7 +88,9 @@ long arch_do_domctl(
if ( np == 0 )
ret = 0;
- else if ( domctl->u.ioport_permission.allow_access )
+ else if ( xsm_ioport_permission(d, fp, fp + np - 1, allow) )
+ ret = -EPERM;
+ else if ( allow )
ret = ioports_permit_access(d, fp, fp + np - 1);
else
ret = ioports_deny_access(d, fp, fp + np - 1);
@@ -822,6 +825,7 @@ long arch_do_domctl(
unsigned long gfn = domctl->u.memory_mapping.first_gfn;
unsigned long mfn = domctl->u.memory_mapping.first_mfn;
unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns;
+ int add = domctl->u.memory_mapping.add_mapping;
int i;
ret = -EINVAL;
@@ -837,8 +841,13 @@ long arch_do_domctl(
if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
break;
- ret=0;
- if ( domctl->u.memory_mapping.add_mapping )
+ ret = xsm_iomem_permission(d, mfn, mfn + nr_mfns - 1, add);
+ if ( ret ) {
+ rcu_unlock_domain(d);
+ break;
+ }
+
+ if ( add )
{
gdprintk(XENLOG_INFO,
"memory_map:add: gfn=%lx mfn=%lx nr_mfns=%lx\n",
@@ -871,6 +880,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;
struct g2m_ioport *g2m_ioport;
int found = 0;
@@ -893,8 +903,14 @@ long arch_do_domctl(
if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
break;
+ ret = xsm_ioport_permission(d, fmp, fmp + np - 1, add);
+ if ( ret ) {
+ rcu_unlock_domain(d);
+ break;
+ }
+
hd = domain_hvm_iommu(d);
- if ( domctl->u.ioport_mapping.add_mapping )
+ if ( add )
{
gdprintk(XENLOG_INFO,
"ioport_map:add f_gport=%x f_mport=%x np=%x\n",
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 9149096507..b1c5d421f3 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -18,6 +18,7 @@
#include <xen/iocap.h>
#include <xen/iommu.h>
#include <xen/trace.h>
+#include <xsm/xsm.h>
#include <asm/msi.h>
#include <asm/current.h>
#include <asm/flushtlb.h>
@@ -1817,6 +1818,14 @@ int map_domain_pirq(
return 0;
}
+ ret = xsm_irq_permission(d, irq, 1);
+ if ( ret )
+ {
+ dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
+ d->domain_id, irq, pirq);
+ return ret;
+ }
+
ret = irq_permit_access(d, pirq);
if ( ret )
{
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 5c7ab68147..5a4acaef69 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -229,6 +229,10 @@ int physdev_unmap_pirq(domid_t domid, int pirq)
if ( !IS_PRIV_FOR(current->domain, d) )
goto free_domain;
+ ret = xsm_irq_permission(d, pirq, 0);
+ if ( ret )
+ goto free_domain;
+
spin_lock(&pcidevs_lock);
spin_lock(&d->event_lock);
ret = unmap_domain_pirq(d, pirq);