diff --git a/tools/flask/policy/modules/nic_dev.te b/tools/flask/policy/modules/nic_dev.te
index e0484af..5206f1e 100644
--- a/tools/flask/policy/modules/nic_dev.te
+++ b/tools/flask/policy/modules/nic_dev.te
@@ -11,4 +11,4 @@
 type nic_dev_t, resource_type;
 
 admin_device(dom0_t, nic_dev_t)
-use_device(domU_t, nic_dev_t)
+use_device_noiommu(domU_t, nic_dev_t)
diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules/xen.if
index ed0df4f..9126400 100644
--- a/tools/flask/policy/modules/xen.if
+++ b/tools/flask/policy/modules/xen.if
@@ -167,11 +167,32 @@ define(`make_device_model', `
 #
 ################################################################################
 
-# use_device(domain, device)
+# use_device_iommu(domain, device)
 #   Allow a device to be used by a domain
-define(`use_device', `
+#   only if an IOMMU provides isolation.
+define(`use_device_iommu', `
     allow $1 $1_self:mmu exchange;
-    allow $1 $2:resource use;
+    allow $1 $2:resource use_iommu;
+    allow $1 domio_t:mmu { map_read map_write };
+')
+
+# use_device_iommu_nointremap(domain, device)
+#   Allow a device to be used by a domain
+#   only if an IOMMU is active, even if it does not support
+#   interrupt remapping.
+#   Allows acceptance of (typically older) less isolating hardware.
+define(`use_device_iommu_nointremap', `
+    allow $1 $1_self:mmu exchange;
+    allow $1 $2:resource { use_iommu use_iommu_nointremap };
+    allow $1 domio_t:mmu { map_read map_write };
+')
+
+# use_device_noiommu(domain, device)
+#   Allow a device to be used by a domain
+#   even without an IOMMU available.
+define(`use_device_noiommu', `
+    allow $1 $1_self:mmu exchange;
+    allow $1 $2:resource { use_iommu use_iommu_nointremap use_noiommu };
     allow $1 domio_t:mmu { map_read map_write };
 ')
 
@@ -180,7 +201,7 @@ define(`use_device', `
 define(`admin_device', `
     allow $1 $2:resource { setup stat_device add_device add_irq add_iomem add_ioport remove_device remove_irq remove_iomem remove_ioport plug unplug };
     allow $1 $2:hvm bind_irq;
-    use_device($1, $2)
+    use_device_noiommu($1, $2)
 ')
 
 # delegate_devices(priv-domain, target-domain)
diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
index 0cff2df..3dbf93d 100644
--- a/tools/flask/policy/modules/xen.te
+++ b/tools/flask/policy/modules/xen.te
@@ -67,7 +67,8 @@ allow xen_t resource_type : resource { remove_irq remove_ioport remove_iomem };
 neverallow * ~domain_type:domain { create transition };
 
 # Resources must be declared using resource_type
-neverallow * ~resource_type:resource use;
+neverallow * ~resource_type:resource { use use_iommu use_iommu_nointremap
+                                       use_noiommu };
 
 # Events must use event_type (see create_channel for a template)
 neverallow ~event_type *:event bind;
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 9114627..276ca97 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -20,6 +20,7 @@
 #include <xen/errno.h>
 #include <xen/guest_access.h>
 #include <xen/xenoprof.h>
+#include <xen/iommu.h>
 #ifdef CONFIG_HAS_PCI
 #include <asm/msi.h>
 #endif
@@ -886,11 +887,31 @@ static int flask_map_domain_msi (struct domain *d, int irq, void *data,
 #endif
 }
 
+static u32 flask_iommu_resource_use_perm(void)
+{
+    /* Obtain the permission level required for allowing a domain
+     * to use an assigned device.
+     *
+     * An active IOMMU with interrupt remapping capability is essential
+     * for ensuring strict isolation of devices, so provide a distinct
+     * permission for that case and also enable optional support for
+     * less capable hardware (no IOMMU or IOMMU missing intremap capability)
+     * via other separate permissions.
+     */
+    u32 perm = RESOURCE__USE_NOIOMMU;
+
+    if (iommu_enabled)
+        perm = ( iommu_intremap ? RESOURCE__USE_IOMMU :
+                                  RESOURCE__USE_IOMMU_NOINTREMAP );
+    return perm;
+}
+
 static int flask_map_domain_irq (struct domain *d, int irq, void *data)
 {
     u32 sid, dsid;
     int rc = -EPERM;
     struct avc_audit_data ad;
+    u32 dperm = flask_iommu_resource_use_perm();
 
     if ( irq >= nr_static_irqs && data ) {
         rc = flask_map_domain_msi(d, irq, data, &sid, &ad);
@@ -907,7 +928,7 @@ static int flask_map_domain_irq (struct domain *d, int irq, void *data)
     if ( rc )
         return rc;
 
-    rc = avc_has_perm(dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    rc = avc_has_perm(dsid, sid, SECCLASS_RESOURCE, dperm, &ad);
     return rc;
 }
 
@@ -956,6 +977,7 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b
     int rc = -EPERM;
     int irq;
     struct avc_audit_data ad;
+    u32 dperm = flask_iommu_resource_use_perm();
 
     rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
     if ( rc )
@@ -972,7 +994,7 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b
         return rc;
 
     dsid = domain_sid(d);
-    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
 }
 
 static int flask_unbind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
@@ -990,6 +1012,7 @@ struct iomem_has_perm_data {
     u32 ssid;
     u32 dsid;
     u32 perm;
+    u32 use_perm;
 };
 
 static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long end)
@@ -1007,7 +1030,7 @@ static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long
     if ( rc )
         return rc;
 
-    return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, data->use_perm, &ad);
 }
 
 static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end, uint8_t access)
@@ -1027,6 +1050,7 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end
 
     data.ssid = domain_sid(current->domain);
     data.dsid = domain_sid(d);
+    data.use_perm = flask_iommu_resource_use_perm();
 
     return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data);
 }
@@ -1041,7 +1065,7 @@ static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, u
     u32 dsid, rsid;
     int rc = -EPERM;
     struct avc_audit_data ad;
-    u32 perm = RESOURCE__USE;
+    u32 perm;
 
     rc = security_device_sid(machine_bdf, &rsid);
     if ( rc )
@@ -1050,6 +1074,8 @@ static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, u
     /* Writes to the BARs count as setup */
     if ( access && (end >= 0x10 && start < 0x28) )
         perm = RESOURCE__SETUP;
+    else
+        perm = flask_iommu_resource_use_perm();
 
     AVC_AUDIT_DATA_INIT(&ad, DEV);
     ad.device = (unsigned long) machine_bdf;
@@ -1279,6 +1305,7 @@ static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
     u32 dsid, rsid;
     int rc = -EPERM;
     struct avc_audit_data ad;
+    u32 dperm = flask_iommu_resource_use_perm();
 
     rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
     if ( rc )
@@ -1295,7 +1322,7 @@ static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
         return rc;
 
     dsid = domain_sid(d);
-    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
 }
 
 static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
@@ -1334,6 +1361,7 @@ static int flask_assign_dtdevice(struct domain *d, const char *dtpath)
     u32 dsid, rsid;
     int rc = -EPERM;
     struct avc_audit_data ad;
+    u32 dperm = flask_iommu_resource_use_perm();
 
     rc = current_has_perm(d, SECCLASS_RESOURCE, RESOURCE__ADD);
     if ( rc )
@@ -1350,7 +1378,7 @@ static int flask_assign_dtdevice(struct domain *d, const char *dtpath)
         return rc;
 
     dsid = domain_sid(d);
-    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    return avc_has_perm(dsid, rsid, SECCLASS_RESOURCE, dperm, &ad);
 }
 
 static int flask_deassign_dtdevice(struct domain *d, const char *dtpath)
@@ -1476,6 +1504,7 @@ struct ioport_has_perm_data {
     u32 ssid;
     u32 dsid;
     u32 perm;
+    u32 use_perm;
 };
 
 static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long end)
@@ -1493,7 +1522,7 @@ static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long
     if ( rc )
         return rc;
 
-    return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad);
+    return avc_has_perm(data->dsid, sid, SECCLASS_RESOURCE, data->use_perm, &ad);
 }
 
 static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t end, uint8_t access)
@@ -1514,6 +1543,7 @@ static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t en
 
     data.ssid = domain_sid(current->domain);
     data.dsid = domain_sid(d);
+    data.use_perm = flask_iommu_resource_use_perm();
 
     return security_iterate_ioport_sids(start, end, _ioport_has_perm, &data);
 }
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 1f7eb35..f276f04 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -420,11 +420,27 @@ class resource
 #  source = domain making the hypercall
 #  target = domain which will no longer have access to the resource
     remove
+# checked when using some core Xen devices (target xen_t)
+#  source = domain which will have access to the resource
+#  target = xen_t
+    use
 # checked when adding a resource to a domain:
 #  source = domain which will have access to the resource
 #  target = resource's security label
-# also checked when using some core Xen devices (target xen_t)
-    use
+# Requires an active IOMMU capable of interrupt remapping in order to
+# enforce isolation.
+    use_iommu
+# checked when adding a resource to a domain when an IOMMU is available
+# but it is not capable of interrupt mapping:
+#  source = domain which will have access to the resource
+#  target = resource's security label
+# Enable this to allow some less secure systems to still work.
+    use_iommu_nointremap
+# checked when adding a resource to a domain when no IOMMU present:
+#  source = domain which will have access to the resource
+#  target = resource's security label
+# Enable this to allow resource use without an active IOMMU.
+    use_noiommu
 # PHYSDEVOP_map_pirq and ioapic writes for dom0, when acting on real IRQs
 #  For GSI interrupts, the IRQ's label is indexed by the IRQ number
 #  For MSI interrupts, the label of the PCI device is used
