aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/domctl.c24
-rw-r--r--xen/arch/x86/irq.c9
-rw-r--r--xen/arch/x86/physdev.c4
-rw-r--r--xen/common/domctl.c10
-rw-r--r--xen/common/rangeset.c8
-rw-r--r--xen/include/xsm/xsm.h22
-rw-r--r--xen/xsm/dummy.c14
-rw-r--r--xen/xsm/flask/hooks.c73
8 files changed, 81 insertions, 83 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);
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 6705a573df..06594a0f01 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -858,6 +858,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
{
struct domain *d;
unsigned int pirq = op->u.irq_permission.pirq;
+ int allow = op->u.irq_permission.allow_access;
ret = -ESRCH;
d = rcu_lock_domain_by_id(op->domain);
@@ -866,7 +867,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( pirq >= d->nr_pirqs )
ret = -EINVAL;
- else if ( op->u.irq_permission.allow_access )
+ else if ( xsm_irq_permission(d, pirq, allow) )
+ ret = -EPERM;
+ else if ( allow )
ret = irq_permit_access(d, pirq);
else
ret = irq_deny_access(d, pirq);
@@ -880,6 +883,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
struct domain *d;
unsigned long mfn = op->u.iomem_permission.first_mfn;
unsigned long nr_mfns = op->u.iomem_permission.nr_mfns;
+ int allow = op->u.iomem_permission.allow_access;
ret = -EINVAL;
if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */
@@ -890,7 +894,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
if ( d == NULL )
break;
- if ( op->u.iomem_permission.allow_access )
+ if ( xsm_iomem_permission(d, mfn, mfn + nr_mfns - 1, allow) )
+ ret = -EPERM;
+ else if ( allow )
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
else
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c
index bb9523fda6..f09c0c4453 100644
--- a/xen/common/rangeset.c
+++ b/xen/common/rangeset.c
@@ -97,10 +97,6 @@ int rangeset_add_range(
struct range *x, *y;
int rc = 0;
- rc = xsm_add_range(r->domain, r->name, s, e);
- if ( rc )
- return rc;
-
ASSERT(s <= e);
spin_lock(&r->lock);
@@ -169,10 +165,6 @@ int rangeset_remove_range(
struct range *x, *y, *t;
int rc = 0;
- rc = xsm_remove_range(r->domain, r->name, s, e);
- if ( rc )
- return rc;
-
ASSERT(s <= e);
spin_lock(&r->lock);
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index e8111a46b7..0afe49f437 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -106,8 +106,8 @@ struct xsm_operations {
int (*kexec) (void);
int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
- int (*add_range) (struct domain *d, char *name, unsigned long s, unsigned long e);
- int (*remove_range) (struct domain *d, char *name, unsigned long s, unsigned long e);
+ int (*irq_permission) (struct domain *d, int pirq, uint8_t allow);
+ int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow);
int (*test_assign_device) (uint32_t machine_bdf);
int (*assign_device) (struct domain *d, uint32_t machine_bdf);
@@ -152,6 +152,7 @@ struct xsm_operations {
int (*pin_mem_cacheattr) (struct domain *d);
int (*ext_vcpucontext) (struct domain *d, uint32_t cmd);
int (*vcpuextstate) (struct domain *d, uint32_t cmd);
+ int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow);
#endif
};
@@ -415,16 +416,14 @@ static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2)
return xsm_call(schedop_shutdown(d1, d2));
}
-static inline int xsm_add_range (struct domain *d, char *name, unsigned long s,
- unsigned long e)
+static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow)
{
- return xsm_call(add_range(d, name, s, e));
+ return xsm_call(irq_permission(d, pirq, allow));
}
-
-static inline int xsm_remove_range (struct domain *d, char *name, unsigned long s,
- unsigned long e)
+
+static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
{
- return xsm_call(remove_range(d, name, s, e));
+ return xsm_call(iomem_permission(d, s, e, allow));
}
static inline int xsm_test_assign_device(uint32_t machine_bdf)
@@ -640,6 +639,11 @@ static inline int xsm_vcpuextstate(struct domain *d, uint32_t cmd)
{
return xsm_call(vcpuextstate(d, cmd));
}
+
+static inline int xsm_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+{
+ return xsm_call(ioport_permission(d, s, e, allow));
+}
#endif /* CONFIG_X86 */
extern struct xsm_operations dummy_xsm_ops;
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index ef461e6ea8..a629396afe 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -273,13 +273,12 @@ static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op)
return -ENOSYS;
}
-static int dummy_add_range (struct domain *d, char *name, unsigned long s, unsigned long e)
+static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow)
{
return 0;
}
-static int dummy_remove_range (struct domain *d, char *name, unsigned long s,
- unsigned long e)
+static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
{
return 0;
}
@@ -462,6 +461,10 @@ static int dummy_vcpuextstate (struct domain *d, uint32_t cmd)
return 0;
}
+static int dummy_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+{
+ return 0;
+}
#endif
struct xsm_operations dummy_xsm_ops;
@@ -536,8 +539,8 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, kexec);
set_to_dummy_if_null(ops, schedop_shutdown);
- set_to_dummy_if_null(ops, add_range);
- set_to_dummy_if_null(ops, remove_range);
+ set_to_dummy_if_null(ops, irq_permission);
+ set_to_dummy_if_null(ops, iomem_permission);
set_to_dummy_if_null(ops, __do_xsm_op);
@@ -577,5 +580,6 @@ void xsm_fixup_ops (struct xsm_operations *ops)
set_to_dummy_if_null(ops, pin_mem_cacheattr);
set_to_dummy_if_null(ops, ext_vcpucontext);
set_to_dummy_if_null(ops, vcpuextstate);
+ set_to_dummy_if_null(ops, ioport_permission);
#endif
}
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 80c1f7017f..1bea49869d 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -643,7 +643,7 @@ static inline u32 resource_to_perm(uint8_t access)
return RESOURCE__REMOVE;
}
-static int irq_has_perm(struct domain *d, uint8_t pirq, uint8_t access)
+static int flask_irq_permission (struct domain *d, int pirq, uint8_t access)
{
u32 perm;
u32 rsid;
@@ -678,10 +678,9 @@ static int irq_has_perm(struct domain *d, uint8_t pirq, uint8_t access)
return rc;
if ( access )
- return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
+ rc = avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
RESOURCE__USE, &ad);
- else
- return rc;
+ return rc;
}
struct iomem_has_perm_data {
@@ -706,7 +705,7 @@ static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long
return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
}
-static int iomem_has_perm(struct domain *d, unsigned long start, unsigned long end, uint8_t access)
+static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end, uint8_t access)
{
struct iomem_has_perm_data data;
int rc;
@@ -784,7 +783,7 @@ static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long
}
-static int ioport_has_perm(struct domain *d, uint32_t start, uint32_t end, uint8_t access)
+static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t end, uint8_t access)
{
int rc;
struct ioport_has_perm_data data;
@@ -1142,23 +1141,30 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b
{
u32 rsid;
int rc = -EPERM;
+ int irq;
struct domain_security_struct *ssec, *tsec;
+ struct avc_audit_data ad;
rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD);
if ( rc )
return rc;
- rc = security_pirq_sid(bind->machine_irq, &rsid);
+ irq = domain_pirq_to_irq(d, bind->machine_irq);
+
+ rc = security_pirq_sid(irq, &rsid);
if ( rc )
return rc;
+ AVC_AUDIT_DATA_INIT(&ad, DEV);
+ ad.device = (unsigned long)irq;
+
ssec = current->domain->ssid;
- rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, NULL);
+ rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad);
if ( rc )
return rc;
tsec = d->ssid;
- return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, NULL);
+ return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
}
static int flask_pin_mem_cacheattr (struct domain *d)
@@ -1205,50 +1211,6 @@ static int flask_vcpuextstate (struct domain *d, uint32_t cmd)
}
#endif
-static int io_has_perm(struct domain *d, char *name, unsigned long s,
- unsigned long e, u32 access)
-{
- int rc = -EPERM;
-
- if ( strcmp(name, "I/O Memory") == 0 )
- {
- rc = iomem_has_perm(d, s, e, access);
- if ( rc )
- return rc;
- }
- else if ( strcmp(name, "Interrupts") == 0 )
- {
- while (s <= e) {
- rc = irq_has_perm(d, s, access);
- if ( rc )
- return rc;
- s++;
- }
- }
-#ifdef CONFIG_X86
- else if ( strcmp(name, "I/O Ports") == 0 )
- {
- rc = ioport_has_perm(d, s, e, access);
- if ( rc )
- return rc;
- }
-#endif
-
- return rc;
-}
-
-static int flask_add_range(struct domain *d, char *name, unsigned long s,
- unsigned long e)
-{
- return io_has_perm(d, name, s, e, 1);
-}
-
-static int flask_remove_range(struct domain *d, char *name, unsigned long s,
- unsigned long e)
-{
- return io_has_perm(d, name, s, e, 0);
-}
-
long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op);
static struct xsm_operations flask_ops = {
@@ -1308,8 +1270,8 @@ static struct xsm_operations flask_ops = {
.kexec = flask_kexec,
.schedop_shutdown = flask_schedop_shutdown,
- .add_range = flask_add_range,
- .remove_range = flask_remove_range,
+ .irq_permission = flask_irq_permission,
+ .iomem_permission = flask_iomem_permission,
.__do_xsm_op = do_flask_op,
@@ -1348,6 +1310,7 @@ static struct xsm_operations flask_ops = {
.pin_mem_cacheattr = flask_pin_mem_cacheattr,
.ext_vcpucontext = flask_ext_vcpucontext,
.vcpuextstate = flask_vcpuextstate,
+ .ioport_permission = flask_ioport_permission,
#endif
};