Since the introduction of the FLASK security module, new hypercalls and access paths have been added to Xen without corresponding XSM hooks. This series adds access checks on these operations and also fixes some bugs in error paths. [PATCH 1/8] xsm/flask: Add missing unlock on error path [PATCH 2/8] xsm/flask: report memory and IO ranges in audit messages [PATCH 3/8] xsm: only log dummy override if not setting up [PATCH 4/8] xsm: add remote_remap permission [PATCH 5/8] xsm: Add missing access checks [PATCH 6/8] xsm: fix up dummy ops [PATCH 7/8] xsm: add checks on PCI configuration access [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
Daniel De Graaf
2011-Dec-13 20:38 UTC
[PATCH 1/8] xsm/flask: Add missing unlock on error path
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/ss/services.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index c810e9b..7b08e73 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1428,6 +1428,7 @@ int security_load_policy(void *data, size_t len) } if ( validate_classes(&policydb) ) { + LOAD_UNLOCK; printk(KERN_ERR "Flask: the definition of a class is incorrect\n"); sidtab_destroy(&sidtab); -- 1.7.7.4
Daniel De Graaf
2011-Dec-13 20:38 UTC
[PATCH 2/8] xsm/flask: report memory and IO ranges in audit messages
This information is useful when determining the cause of an AVC denial caused by missing label on device memory or IRQs. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/avc.c | 11 ++++++++++- xen/xsm/flask/hooks.c | 18 ++++++++++-------- xen/xsm/flask/include/avc.h | 13 +++++++++++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c index c47dd40..9475d92 100644 --- a/xen/xsm/flask/avc.c +++ b/xen/xsm/flask/avc.c @@ -568,8 +568,17 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, d = a->d; if ( d ) printk("domid=%d ", d->domain_id); - if ( a && a->device ) + switch ( a ? a->type : 0 ) { + case AVC_AUDIT_DATA_DEV: printk("device=0x%lx ", a->device); + break; + case AVC_AUDIT_DATA_IRQ: + printk("irq=%d ", a->irq); + break; + case AVC_AUDIT_DATA_RANGE: + printk("range=0x%lx-0x%lx ", a->range.start, a->range.end); + break; + } avc_dump_query(ssid, tsid, tclass); printk("\n"); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 0feb070..1a3f3b3 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -670,8 +670,8 @@ static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) if ( rc ) return rc; - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = (unsigned long) pirq; + AVC_AUDIT_DATA_INIT(&ad, IRQ); + ad.irq = pirq; rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); if ( rc ) @@ -694,8 +694,9 @@ static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long struct avc_audit_data ad; int rc = -EPERM; - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = start; + AVC_AUDIT_DATA_INIT(&ad, RANGE); + ad.range.start = start; + ad.range.end = end; rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); @@ -771,8 +772,9 @@ static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long struct avc_audit_data ad; int rc; - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = start; + AVC_AUDIT_DATA_INIT(&ad, RANGE); + ad.range.start = start; + ad.range.end = end; rc = avc_has_perm(data->ssec->sid, sid, SECCLASS_RESOURCE, data->perm, &ad); @@ -1155,8 +1157,8 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b if ( rc ) return rc; - AVC_AUDIT_DATA_INIT(&ad, DEV); - ad.device = (unsigned long)irq; + AVC_AUDIT_DATA_INIT(&ad, IRQ); + ad.irq = irq; ssec = current->domain->ssid; rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad); diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h index 2168585..1b19189 100644 --- a/xen/xsm/flask/include/avc.h +++ b/xen/xsm/flask/include/avc.h @@ -38,9 +38,18 @@ struct sk_buff; /* Auxiliary data to use in generating the audit record. */ struct avc_audit_data { char type; -#define AVC_AUDIT_DATA_DEV 1 +#define AVC_AUDIT_DATA_DEV 1 +#define AVC_AUDIT_DATA_IRQ 2 +#define AVC_AUDIT_DATA_RANGE 3 struct domain *d; - unsigned long device; + union { + unsigned long device; + int irq; + struct { + unsigned long start; + unsigned long end; + } range; + }; }; #define v4info fam.v4 -- 1.7.7.4
Daniel De Graaf
2011-Dec-13 20:38 UTC
[PATCH 3/8] xsm: only log dummy override if not setting up dummy_xsm_ops
The log messages from dummy overrides appear on every boot with XSM enabled, and are just noise when filling in the dummy_xsm_ops structure. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/dummy.c | 17 +++++++++-------- 1 files changed, 9 insertions(+), 8 deletions(-) diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index a629396..d6f2da0 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -469,14 +469,15 @@ static int dummy_ioport_permission (struct domain *d, uint32_t s, uint32_t e, ui struct xsm_operations dummy_xsm_ops; -#define set_to_dummy_if_null(ops, function) \ - do { \ - if ( !ops->function ) \ - { \ - ops->function = dummy_##function; \ - dprintk(XENLOG_DEBUG, "Had to override the " #function \ - " security operation with the dummy one.\n"); \ - } \ +#define set_to_dummy_if_null(ops, function) \ + do { \ + if ( !ops->function ) \ + { \ + ops->function = dummy_##function; \ + if (ops != &dummy_xsm_ops) \ + dprintk(XENLOG_DEBUG, "Had to override the " #function \ + " security operation with the dummy one.\n"); \ + } \ } while (0) void xsm_fixup_ops (struct xsm_operations *ops) -- 1.7.7.4
The mmu_update hypercall can be used to manipulate the page tables of a remote domain. Add a check for this in the XSM hook in addition to the existing check on mapping pages of a remote domain. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 1 + xen/arch/x86/mm.c | 2 +- xen/include/xsm/xsm.h | 10 +++++----- xen/xsm/dummy.c | 4 ++-- xen/xsm/flask/hooks.c | 9 +++++++-- xen/xsm/flask/include/av_perm_to_string.h | 1 + xen/xsm/flask/include/av_permissions.h | 1 + 7 files changed, 18 insertions(+), 10 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 1b2687a..38036d0 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -128,6 +128,7 @@ class mmu pinpage mfnlist memorymap + remote_remap } class shadow diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 7bb3ea1..19391fc 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3517,7 +3517,7 @@ int do_mmu_update( { p2m_type_t p2mt; - rc = xsm_mmu_normal_update(d, pg_owner, req.val); + rc = xsm_mmu_normal_update(d, pt_owner, pg_owner, req.val); if ( rc ) break; rc = -EINVAL; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index ce3b6aa..43829c7 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -141,8 +141,8 @@ struct xsm_operations { int (*getidletime) (void); int (*machine_memory_map) (void); int (*domain_memory_map) (struct domain *d); - int (*mmu_normal_update) (struct domain *d, struct domain *f, - intpte_t fpte); + int (*mmu_normal_update) (struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte); int (*mmu_machphys_update) (struct domain *d, unsigned long mfn); int (*update_va_mapping) (struct domain *d, struct domain *f, l1_pgentry_t pte); @@ -593,10 +593,10 @@ static inline int xsm_domain_memory_map(struct domain *d) return xsm_call(domain_memory_map(d)); } -static inline int xsm_mmu_normal_update (struct domain *d, struct domain *f, - intpte_t fpte) +static inline int xsm_mmu_normal_update (struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte) { - return xsm_call(mmu_normal_update(d, f, fpte)); + return xsm_call(mmu_normal_update(d, t, f, fpte)); } static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn) diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index d6f2da0..7066dfb 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -399,8 +399,8 @@ static int dummy_domain_memory_map (struct domain *d) return 0; } -static int dummy_mmu_normal_update (struct domain *d, struct domain *f, - intpte_t fpte) +static int dummy_mmu_normal_update (struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte) { return 0; } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 1a3f3b3..04c2f68 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -1008,8 +1008,8 @@ static int flask_domain_memory_map(struct domain *d) return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__MEMORYMAP); } -static int flask_mmu_normal_update(struct domain *d, struct domain *f, - intpte_t fpte) +static int flask_mmu_normal_update(struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte) { int rc = 0; u32 map_perms = MMU__MAP_READ; @@ -1017,6 +1017,11 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *f, struct domain_security_struct *dsec; u32 fsid; + if (d != t) + rc = domain_has_perm(d, t, SECCLASS_MMU, MMU__REMOTE_REMAP); + if ( rc ) + return rc; + if ( !(l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_PRESENT) ) return 0; diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 70aa02d..56572a7 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -87,6 +87,7 @@ S_(SECCLASS_MMU, MMU__PINPAGE, "pinpage") S_(SECCLASS_MMU, MMU__MFNLIST, "mfnlist") S_(SECCLASS_MMU, MMU__MEMORYMAP, "memorymap") + S_(SECCLASS_MMU, MMU__REMOTE_REMAP, "remote_remap") S_(SECCLASS_SHADOW, SHADOW__DISABLE, "disable") S_(SECCLASS_SHADOW, SHADOW__ENABLE, "enable") S_(SECCLASS_SHADOW, SHADOW__LOGDIRTY, "logdirty") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index 4c2ffb6..67511ad 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -92,6 +92,7 @@ #define MMU__PINPAGE 0x00000200UL #define MMU__MFNLIST 0x00000400UL #define MMU__MEMORYMAP 0x00000800UL +#define MMU__REMOTE_REMAP 0x00001000UL #define SHADOW__DISABLE 0x00000001UL #define SHADOW__ENABLE 0x00000002UL -- 1.7.7.4
Actions requiring IS_PRIV should also require some XSM access control in order for XSM to be useful in confining multiple privileged domains. Add XSM hooks for new hypercalls and sub-commands that are under IS_PRIV but not currently under any access checks. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 14 ++ xen/arch/ia64/xen/mm.c | 8 + xen/arch/x86/cpu/mcheck/mce.c | 4 + xen/arch/x86/domctl.c | 17 ++- xen/arch/x86/hvm/hvm.c | 26 +++ xen/arch/x86/mm.c | 10 +- xen/arch/x86/msi.c | 6 + xen/arch/x86/physdev.c | 9 + xen/arch/x86/platform_hypercall.c | 28 +++ xen/arch/x86/sysctl.c | 14 ++ xen/common/domctl.c | 10 +- xen/common/grant_table.c | 10 + xen/common/sysctl.c | 17 ++ xen/drivers/passthrough/iommu.c | 8 + xen/drivers/passthrough/pci.c | 17 ++- xen/include/xsm/xsm.h | 122 +++++++++++++ xen/xsm/flask/hooks.c | 221 +++++++++++++++++++++++- xen/xsm/flask/include/av_perm_to_string.h | 14 ++ xen/xsm/flask/include/av_permissions.h | 14 ++ 19 files changed, 556 insertions(+), 13 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 38036d0..644f2e1 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -45,6 +45,11 @@ class xen debug getcpuinfo heap + pm_op + mca_op + lockprof + cpupool_op + sched_op } class domain @@ -77,6 +82,9 @@ class domain setextvcpucontext getvcpuextstate setvcpuextstate + getpodtarget + setpodtarget + set_misc_info } class hvm @@ -91,6 +99,9 @@ class hvm bind_irq cacheattr trackdirtyvram + hvmctl + mem_event + mem_sharing } class event @@ -152,6 +163,9 @@ class resource stat_device add_device remove_device + plug + unplug + setup } class security diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index d440e4d..694bf95 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -3496,6 +3496,14 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) return rc; if ( op == XENMEM_set_pod_target ) + rc = xsm_set_pod_target(d); + else + rc = xsm_get_pod_target(d); + + if ( rc != 0 ) + goto pod_target_out_unlock; + + if ( op == XENMEM_set_pod_target ) { /* if -ENOSYS is returned, domain builder aborts domain creation. */ diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c index 6af93c0..b592041 100644 --- a/xen/arch/x86/cpu/mcheck/mce.c +++ b/xen/arch/x86/cpu/mcheck/mce.c @@ -1384,6 +1384,10 @@ long do_mca(XEN_GUEST_HANDLE(xen_mc_t) u_xen_mc) if (!IS_PRIV(v->domain) ) return x86_mcerr(NULL, -EPERM); + ret = xsm_do_mca(); + if ( ret ) + return x86_mcerr(NULL, ret); + if ( copy_from_guest(op, u_xen_mc, 1) ) return x86_mcerr("do_mca: failed copyin of xen_mc_t", -EFAULT); diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 4e258f3..9c9d5d1 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1441,8 +1441,10 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = mem_event_domctl(d, &domctl->u.mem_event_op, - guest_handle_cast(u_domctl, void)); + ret = xsm_mem_event(d); + if ( !ret ) + ret = mem_event_domctl(d, &domctl->u.mem_event_op, + guest_handle_cast(u_domctl, void)); rcu_unlock_domain(d); copy_to_guest(u_domctl, domctl, 1); } @@ -1457,7 +1459,9 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op); + ret = xsm_mem_sharing(d); + if ( !ret ) + ret = mem_sharing_domctl(d, &domctl->u.mem_sharing_op); rcu_unlock_domain(d); copy_to_guest(u_domctl, domctl, 1); } @@ -1498,8 +1502,11 @@ long arch_do_domctl( d = rcu_lock_domain_by_id(domctl->domain); if ( d != NULL ) { - p2m = p2m_get_hostp2m(d); - p2m->access_required = domctl->u.access_required.access_required; + ret = xsm_mem_event(d); + if ( !ret ) { + p2m = p2m_get_hostp2m(d); + p2m->access_required = domctl->u.access_required.access_required; + } rcu_unlock_domain(d); } } diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 901132d..bae3696 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3869,6 +3869,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( rc != 0 ) return rc; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail_getmemtype; + rc = -EINVAL; if ( is_hvm_domain(d) ) { @@ -3883,6 +3887,8 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) a.mem_type = HVMMEM_mmio_dm; rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0; } + + param_fail_getmemtype: rcu_unlock_domain(d); break; } @@ -3911,6 +3917,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) ) goto param_fail4; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail4; + rc = -EINVAL; if ( (a.first_pfn > domain_get_maximum_gpfn(d)) || ((a.first_pfn + a.nr - 1) < a.first_pfn) || @@ -3986,6 +3996,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) ) goto param_fail5; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail5; + rc = -EINVAL; if ( (a.first_pfn > domain_get_maximum_gpfn(d)) || ((a.first_pfn + a.nr - 1) < a.first_pfn) || @@ -4016,6 +4030,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) ) goto param_fail6; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail6; + rc = -EINVAL; if ( (a.pfn > domain_get_maximum_gpfn(d)) && a.pfn != ~0ull ) goto param_fail6; @@ -4048,6 +4066,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) || !paging_mode_shadow(d) ) goto param_fail7; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail7; + rc = 0; pagetable_dying(d, a.gpa); @@ -4098,6 +4120,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) if ( !is_hvm_domain(d) ) goto param_fail8; + rc = xsm_hvm_param(d, op); + if ( rc ) + goto param_fail8; + rc = -ENOENT; if ( tr.vcpuid >= d->max_vcpus || (v = d->vcpu[tr.vcpuid]) == NULL ) goto param_fail8; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 19391fc..67f5630 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -5041,7 +5041,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) /* Support DOMID_SELF? */ if ( !IS_PRIV(current->domain) ) - return -EINVAL; + return -EPERM; if ( copy_from_guest(&target, arg, 1) ) return -EFAULT; @@ -5051,6 +5051,14 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) return rc; if ( op == XENMEM_set_pod_target ) + rc = xsm_set_pod_target(d); + else + rc = xsm_get_pod_target(d); + + if ( rc != 0 ) + goto pod_target_out_unlock; + + if ( op == XENMEM_set_pod_target ) { if ( target.target_pages > d->max_pages ) { diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index 2d86006..782b84b 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -29,6 +29,7 @@ #include <io_ports.h> #include <public/physdev.h> #include <xen/iommu.h> +#include <xsm/xsm.h> /* bitmap indicate which fixed map is free */ DEFINE_SPINLOCK(msix_fixmap_lock); @@ -992,6 +993,7 @@ int pci_restore_msi_state(struct pci_dev *pdev) { unsigned long flags; int irq; + int ret; struct msi_desc *entry, *tmp; struct irq_desc *desc; @@ -1000,6 +1002,10 @@ int pci_restore_msi_state(struct pci_dev *pdev) if (!pdev) return -EINVAL; + ret = xsm_resource_setup_pci((pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn); + if ( ret ) + return ret; + list_for_each_entry_safe( entry, tmp, &pdev->msi_list, list ) { irq = entry->irq; diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index c1c7e54..ca4fb59 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -600,6 +600,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) if ( !IS_PRIV(current->domain) ) break; + ret = xsm_resource_setup_misc(); + if ( ret ) + break; + ret = -EFAULT; if ( copy_from_guest(&info, arg, 1) ) break; @@ -662,6 +666,11 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) ret = -EINVAL; if ( setup_gsi.gsi < 0 || setup_gsi.gsi >= nr_irqs_gsi ) break; + + ret = xsm_resource_setup_gsi(setup_gsi.gsi); + if ( ret ) + break; + ret = mp_register_gsi(setup_gsi.gsi, setup_gsi.triggering, setup_gsi.polarity); break; diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index a0d23ba..f9a836a 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -390,6 +390,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) break; case XENPF_set_processor_pminfo: + ret = xsm_setpminfo(); + if ( ret ) + break; + switch ( op->u.set_pminfo.type ) { case XEN_PM_PX: @@ -440,6 +444,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) g_info = &op->u.pcpu_info; + ret = xsm_getcpuinfo(); + if ( ret ) + break; + if ( !get_cpu_maps() ) { ret = -EBUSY; @@ -509,6 +517,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { int cpu = op->u.cpu_ol.cpuid; + ret = xsm_resource_plug_core(); + if ( ret ) + break; + if ( cpu >= nr_cpu_ids || !cpu_present(cpu) ) { ret = -EINVAL; @@ -521,6 +533,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) break; } + ret = xsm_resource_plug_core(); + if ( ret ) + break; + ret = continue_hypercall_on_cpu( 0, cpu_up_helper, (void *)(unsigned long)cpu); break; @@ -530,6 +546,10 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) { int cpu = op->u.cpu_ol.cpuid; + ret = xsm_resource_unplug_core(); + if ( ret ) + break; + if ( cpu == 0 ) { ret = -EOPNOTSUPP; @@ -555,12 +575,20 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) break; case XENPF_cpu_hotadd: + ret = xsm_resource_plug_core(); + if ( ret ) + break; + ret = cpu_add(op->u.cpu_add.apic_id, op->u.cpu_add.acpi_id, op->u.cpu_add.pxm); break; case XENPF_mem_hotadd: + ret = xsm_resource_plug_core(); + if ( ret ) + break; + ret = memory_add(op->u.mem_add.spfn, op->u.mem_add.epfn, op->u.mem_add.pxm); diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 738e517..379f071 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -103,6 +103,10 @@ long arch_do_sysctl( uint32_t i, max_cpu_index, last_online_cpu; xen_sysctl_topologyinfo_t *ti = &sysctl->u.topologyinfo; + ret = xsm_physinfo(); + if ( ret ) + break; + last_online_cpu = cpumask_last(&cpu_online_map); max_cpu_index = min_t(uint32_t, ti->max_cpu_index, last_online_cpu); ti->max_cpu_index = last_online_cpu; @@ -139,6 +143,10 @@ long arch_do_sysctl( uint32_t i, j, max_node_index, last_online_node; xen_sysctl_numainfo_t *ni = &sysctl->u.numainfo; + ret = xsm_physinfo(); + if ( ret ) + break; + last_online_node = last_node(node_online_map); max_node_index = min_t(uint32_t, ni->max_node_index, last_online_node); ni->max_node_index = last_online_node; @@ -189,10 +197,16 @@ long arch_do_sysctl( switch ( sysctl->u.cpu_hotplug.op ) { case XEN_SYSCTL_CPU_HOTPLUG_ONLINE: + ret = xsm_resource_plug_core(); + if ( ret ) + break; ret = continue_hypercall_on_cpu( 0, cpu_up_helper, (void *)(unsigned long)cpu); break; case XEN_SYSCTL_CPU_HOTPLUG_OFFLINE: + ret = xsm_resource_unplug_core(); + if ( ret ) + break; ret = continue_hypercall_on_cpu( 0, cpu_down_helper, (void *)(unsigned long)cpu); break; diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 06594a0..d6ae09b 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -972,9 +972,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) d = rcu_lock_domain_by_id(op->domain); if ( d != NULL ) { - d->suspend_evtchn = op->u.subscribe.port; + ret = xsm_domctl(d, op->cmd); + if ( !ret ) + d->suspend_evtchn = op->u.subscribe.port; rcu_unlock_domain(d); - ret = 0; } } break; @@ -985,9 +986,10 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) ret = -ESRCH; if ( (d = rcu_lock_domain_by_id(op->domain)) != NULL ) { - d->disable_migrate = op->u.disable_migrate.disable; + ret = xsm_domctl(d, op->cmd); + if ( !ret ) + d->disable_migrate = op->u.disable_migrate.disable; rcu_unlock_domain(d); - ret = 0; } } break; diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index e2b103b..fefa838 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -2208,6 +2208,11 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE(gnttab_get_status_frames_t) uop, op.status = GNTST_general_error; goto out1; } + rc = xsm_grant_setup(current->domain, d); + if ( rc ) { + op.status = GNTST_permission_denied; + goto out1; + } gt = d->grant_table; @@ -2259,6 +2264,11 @@ gnttab_get_version(XEN_GUEST_HANDLE(gnttab_get_version_t uop)) rcu_unlock_domain(d); return -EPERM; } + if ( xsm_grant_query_size(current->domain, d) ) + { + rcu_unlock_domain(d); + return -EPERM; + } spin_lock(&d->grant_table->lock); op.version = d->grant_table->gt_version; spin_unlock(&d->grant_table->lock); diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index ccfdb22..f8f7cf8 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -152,6 +152,11 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) #ifdef LOCK_PROFILE case XEN_SYSCTL_lockprof_op: { + ret = xsm_lockprof(); + if ( ret ) + break; + + ret = perfc_control(&op->u.perfc_op); ret = spinlock_profile_control(&op->u.lockprof_op); if ( copy_to_guest(u_sysctl, op, 1) ) ret = -EFAULT; @@ -260,6 +265,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) uint32_t *status, *ptr; unsigned long pfn; + ret = xsm_page_offline(op->u.page_offline.cmd); + if ( ret ) + break; + ptr = status = xmalloc_bytes( sizeof(uint32_t) * (op->u.page_offline.end - op->u.page_offline.start + 1)); @@ -314,6 +323,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) case XEN_SYSCTL_cpupool_op: { + ret = xsm_cpupool_op(); + if ( ret ) + break; + ret = cpupool_do_sysctl(&op->u.cpupool_op); if ( (ret == 0) && copy_to_guest(u_sysctl, op, 1) ) ret = -EFAULT; @@ -322,6 +335,10 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysctl_t) u_sysctl) case XEN_SYSCTL_scheduler_op: { + ret = xsm_sched_op(); + if ( ret ) + break; + ret = sched_adjust_global(&op->u.scheduler_op); if ( (ret == 0) && copy_to_guest(u_sysctl, op, 1) ) ret = -EFAULT; diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index bacca11..d88e9d7 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -425,12 +425,16 @@ static int iommu_get_device_group( ((pdev->bus == bus) && (pdev->devfn == devfn)) ) continue; + if ( xsm_get_device_group((seg << 16) | (pdev->bus << 8) | pdev->devfn) ) + continue; + sdev_id = ops->get_device_group_id(seg, pdev->bus, pdev->devfn); if ( (sdev_id == group_id) && (i < max_sdevs) ) { bdf = 0; bdf |= (pdev->bus & 0xff) << 16; bdf |= (pdev->devfn & 0xff) << 8; + if ( unlikely(copy_to_guest_offset(buf, i, &bdf, 1)) ) { spin_unlock(&pcidevs_lock); @@ -519,6 +523,10 @@ int iommu_do_domctl( u32 max_sdevs; XEN_GUEST_HANDLE_64(uint32) sdevs; + ret = xsm_get_device_group(domctl->u.get_device_group.machine_sbdf); + if ( ret ) + break; + ret = -EINVAL; if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index b7f87d0..50d337a 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -28,6 +28,7 @@ #include <xen/keyhandler.h> #include <xen/radix-tree.h> #include <xen/tasklet.h> +#include <xsm/xsm.h> #ifdef CONFIG_X86 #include <asm/msi.h> #endif @@ -297,7 +298,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info) struct pci_dev *pdev; unsigned int slot = PCI_SLOT(devfn), func = PCI_FUNC(devfn); const char *pdev_type; - int ret = -ENOMEM; + int ret; if (!info) pdev_type = "device"; @@ -318,6 +319,12 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, const struct pci_dev_info *info) pdev_type = "device"; } + ret = xsm_resource_plug_pci((seg << 16) | (bus << 8) | devfn); + if ( ret ) + return ret; + + ret = -ENOMEM; + spin_lock(&pcidevs_lock); pseg = alloc_pseg(seg); if ( !pseg ) @@ -426,7 +433,13 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn) { struct pci_seg *pseg = get_pseg(seg); struct pci_dev *pdev; - int ret = -ENODEV; + int ret; + + ret = xsm_resource_unplug_pci((seg << 16) | (bus << 8) | devfn); + if ( ret ) + return ret; + + ret = -ENODEV; if ( !pseg ) return -ENODEV; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 43829c7..0c7f248 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -63,6 +63,7 @@ struct xsm_operations { int (*getvcpuinfo) (struct domain *d); int (*domain_settime) (struct domain *d); int (*set_target) (struct domain *d, struct domain *e); + int (*domctl) (struct domain *d, int cmd); int (*tbufcontrol) (void); int (*readconsole) (uint32_t clear); int (*sched_id) (void); @@ -74,7 +75,9 @@ struct xsm_operations { int (*getcpuinfo) (void); int (*availheap) (void); int (*get_pmstat) (void); + int (*setpminfo) (void); int (*pm_op) (void); + int (*do_mca) (void); int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2); int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1, @@ -96,6 +99,8 @@ struct xsm_operations { int (*alloc_security_evtchn) (struct evtchn *chn); void (*free_security_evtchn) (struct evtchn *chn); + int (*get_pod_target) (struct domain *d); + int (*set_pod_target) (struct domain *d); int (*memory_adjust_reservation) (struct domain *d1, struct domain *d2); int (*memory_stat_reservation) (struct domain *d1, struct domain *d2); int (*memory_pin_page) (struct domain *d, struct page_info *page); @@ -109,10 +114,24 @@ struct xsm_operations { 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 (*get_device_group) (uint32_t machine_bdf); int (*test_assign_device) (uint32_t machine_bdf); int (*assign_device) (struct domain *d, uint32_t machine_bdf); int (*deassign_device) (struct domain *d, uint32_t machine_bdf); + int (*resource_plug_core) (void); + int (*resource_unplug_core) (void); + int (*resource_plug_pci) (uint32_t machine_bdf); + int (*resource_unplug_pci) (uint32_t machine_bdf); + int (*resource_setup_pci) (uint32_t machine_bdf); + int (*resource_setup_gsi) (int gsi); + int (*resource_setup_misc) (void); + + int (*page_offline)(uint32_t cmd); + int (*lockprof)(void); + int (*cpupool_op)(void); + int (*sched_op)(void); + long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op); #ifdef CONFIG_X86 @@ -128,6 +147,8 @@ struct xsm_operations { int (*hvm_set_isa_irq_level) (struct domain *d); int (*hvm_set_pci_link_route) (struct domain *d); int (*hvm_inject_msi) (struct domain *d); + int (*mem_event) (struct domain *d); + int (*mem_sharing) (struct domain *d); int (*apic) (struct domain *d, int cmd); int (*xen_settime) (void); int (*memtype) (uint32_t access); @@ -149,6 +170,7 @@ struct xsm_operations { int (*add_to_physmap) (struct domain *d1, struct domain *d2); int (*sendtrigger) (struct domain *d); int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind); + int (*unbind_pt_irq) (struct domain *d); int (*pin_mem_cacheattr) (struct domain *d); int (*ext_vcpucontext) (struct domain *d, uint32_t cmd); int (*vcpuextstate) (struct domain *d, uint32_t cmd); @@ -236,6 +258,11 @@ static inline int xsm_set_target (struct domain *d, struct domain *e) return xsm_call(set_target(d, e)); } +static inline int xsm_domctl (struct domain *d, int cmd) +{ + return xsm_call(domctl(d, cmd)); +} + static inline int xsm_tbufcontrol (void) { return xsm_call(tbufcontrol()); @@ -291,11 +318,21 @@ static inline int xsm_get_pmstat(void) return xsm_call(get_pmstat()); } +static inline int xsm_setpminfo(void) +{ + return xsm_call(setpminfo()); +} + static inline int xsm_pm_op(void) { return xsm_call(pm_op()); } +static inline int xsm_do_mca(void) +{ + return xsm_call(do_mca()); +} + static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn, domid_t id2) { @@ -379,6 +416,16 @@ static inline void xsm_free_security_evtchn (struct evtchn *chn) (void)xsm_call(free_security_evtchn(chn)); } +static inline int xsm_get_pod_target (struct domain *d) +{ + return xsm_call(get_pod_target(d)); +} + +static inline int xsm_set_pod_target (struct domain *d) +{ + return xsm_call(set_pod_target(d)); +} + static inline int xsm_memory_adjust_reservation (struct domain *d1, struct domain *d2) { @@ -426,6 +473,11 @@ static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e return xsm_call(iomem_permission(d, s, e, allow)); } +static inline int xsm_get_device_group(uint32_t machine_bdf) +{ + return xsm_call(get_device_group(machine_bdf)); +} + static inline int xsm_test_assign_device(uint32_t machine_bdf) { return xsm_call(test_assign_device(machine_bdf)); @@ -441,6 +493,61 @@ static inline int xsm_deassign_device(struct domain *d, uint32_t machine_bdf) return xsm_call(deassign_device(d, machine_bdf)); } +static inline int xsm_resource_plug_pci (uint32_t machine_bdf) +{ + return xsm_call(resource_plug_pci(machine_bdf)); +} + +static inline int xsm_resource_unplug_pci (uint32_t machine_bdf) +{ + return xsm_call(resource_unplug_pci(machine_bdf)); +} + +static inline int xsm_resource_plug_core (void) +{ + return xsm_call(resource_plug_core()); +} + +static inline int xsm_resource_unplug_core (void) +{ + return xsm_call(resource_unplug_core()); +} + +static inline int xsm_resource_setup_pci (uint32_t machine_bdf) +{ + return xsm_call(resource_setup_pci(machine_bdf)); +} + +static inline int xsm_resource_setup_gsi (int gsi) +{ + return xsm_call(resource_setup_gsi(gsi)); +} + +static inline int xsm_resource_setup_misc (void) +{ + return xsm_call(resource_setup_misc()); +} + +static inline int xsm_page_offline(uint32_t cmd) +{ + return xsm_call(page_offline(cmd)); +} + +static inline int xsm_lockprof(void) +{ + return xsm_call(lockprof()); +} + +static inline int xsm_cpupool_op(void) +{ + return xsm_call(cpupool_op()); +} + +static inline int xsm_sched_op(void) +{ + return xsm_call(sched_op()); +} + static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op) { #ifdef XSM_ENABLE @@ -528,6 +635,16 @@ static inline int xsm_hvm_inject_msi (struct domain *d) return xsm_call(hvm_inject_msi(d)); } +static inline int xsm_mem_event (struct domain *d) +{ + return xsm_call(mem_event(d)); +} + +static inline int xsm_mem_sharing (struct domain *d) +{ + return xsm_call(mem_sharing(d)); +} + static inline int xsm_apic (struct domain *d, int cmd) { return xsm_call(apic(d, cmd)); @@ -626,6 +743,11 @@ static inline int xsm_bind_pt_irq(struct domain *d, return xsm_call(bind_pt_irq(d, bind)); } +static inline int xsm_unbind_pt_irq(struct domain *d) +{ + return xsm_call(unbind_pt_irq(d)); +} + static inline int xsm_pin_mem_cacheattr(struct domain *d) { return xsm_call(pin_mem_cacheattr(d)); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 04c2f68..efe52bb 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -368,6 +368,16 @@ static int get_mfn_sid(unsigned long mfn, u32 *sid) return rc; } +static int flask_get_pod_target(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__GETPODTARGET); +} + +static int flask_set_pod_target(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETPODTARGET); +} + static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2) { return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__ADJUST); @@ -582,6 +592,11 @@ static int flask_set_target(struct domain *d, struct domain *e) return domain_has_perm(d, e, SECCLASS_DOMAIN, DOMAIN__SET_TARGET); } +static int flask_domctl(struct domain *d, int cmd) +{ + return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SET_MISC_INFO); +} + static int flask_tbufcontrol(void) { return domain_has_xen(current->domain, XEN__TBUFCONTROL); @@ -635,6 +650,26 @@ static int flask_availheap(void) return domain_has_xen(current->domain, XEN__HEAP); } +static int flask_get_pmstat(void) +{ + return domain_has_xen(current->domain, XEN__PM_OP); +} + +static int flask_setpminfo(void) +{ + return domain_has_xen(current->domain, XEN__PM_OP); +} + +static int flask_pm_op(void) +{ + return domain_has_xen(current->domain, XEN__PM_OP); +} + +static int flask_do_mca(void) +{ + return domain_has_xen(current->domain, XEN__MCA_OP); +} + static inline u32 resource_to_perm(uint8_t access) { if ( access ) @@ -727,6 +762,135 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } +static int flask_resource_plug_core(void) +{ + struct domain_security_struct *ssec; + + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__PLUG, NULL); +} + +static int flask_resource_unplug_core(void) +{ + struct domain_security_struct *ssec; + + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__UNPLUG, NULL); +} + +static int flask_resource_use_core(void) +{ + struct domain_security_struct *ssec; + + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, SECINITSID_DOMXEN, SECCLASS_RESOURCE, RESOURCE__USE, NULL); +} + +static int flask_resource_plug_pci(uint32_t machine_bdf) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__PLUG, &ad); +} + +static int flask_resource_unplug_pci(uint32_t machine_bdf) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__UNPLUG, &ad); +} + +static int flask_resource_setup_pci(uint32_t machine_bdf) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); +} + +static int flask_resource_setup_gsi(int gsi) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + + rc = security_irq_sid(gsi, &rsid); + if ( rc ) + return rc; + + AVC_AUDIT_DATA_INIT(&ad, IRQ); + ad.irq = gsi; + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); +} + +static int flask_resource_setup_misc(void) +{ + struct domain_security_struct *ssec; + + ssec = current->domain->ssid; + return avc_has_perm(ssec->sid, SECINITSID_XEN, SECCLASS_RESOURCE, RESOURCE__SETUP, NULL); +} + +static inline int flask_page_offline(uint32_t cmd) +{ + switch (cmd) { + case sysctl_page_offline: + return flask_resource_unplug_core(); + case sysctl_page_online: + return flask_resource_plug_core(); + case sysctl_query_page_offline: + return flask_resource_use_core(); + default: + return -EPERM; + } +} + +static inline int flask_lockprof(void) +{ + return domain_has_xen(current->domain, XEN__LOCKPROF); +} + +static inline int flask_cpupool_op(void) +{ + return domain_has_xen(current->domain, XEN__CPUPOOL_OP); +} + +static inline int flask_sched_op(void) +{ + return domain_has_xen(current->domain, XEN__SCHED_OP); +} + static int flask_perfcontrol(void) { return domain_has_xen(current->domain, XEN__PERFCONTROL); @@ -887,8 +1051,11 @@ static int flask_hvm_param(struct domain *d, unsigned long op) case HVMOP_get_param: perm = HVM__GETPARAM; break; + case HVMOP_track_dirty_vram: + perm = HVM__TRACKDIRTYVRAM; + break; default: - return -EPERM; + perm = HVM__HVMCTL; } return domain_has_perm(current->domain, d, SECCLASS_HVM, perm); @@ -909,6 +1076,16 @@ static int flask_hvm_set_pci_link_route(struct domain *d) return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__PCIROUTE); } +static int flask_mem_event(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_EVENT); +} + +static int flask_mem_sharing(struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__MEM_SHARING); +} + static int flask_apic(struct domain *d, int cmd) { u32 perm; @@ -1088,6 +1265,19 @@ static int flask_sendtrigger(struct domain *d) return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__TRIGGER); } +static int flask_get_device_group(uint32_t machine_bdf) +{ + u32 rsid; + int rc = -EPERM; + struct domain_security_struct *ssec = current->domain->ssid; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL); +} + static int flask_test_assign_device(uint32_t machine_bdf) { u32 rsid; @@ -1174,6 +1364,11 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } +static int flask_unbind_pt_irq (struct domain *d) +{ + return domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE); +} + static int flask_pin_mem_cacheattr (struct domain *d) { return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__CACHEATTR); @@ -1236,6 +1431,7 @@ static struct xsm_operations flask_ops = { .getvcpuinfo = flask_getvcpuinfo, .domain_settime = flask_domain_settime, .set_target = flask_set_target, + .domctl = flask_domctl, .tbufcontrol = flask_tbufcontrol, .readconsole = flask_readconsole, .sched_id = flask_sched_id, @@ -1246,6 +1442,10 @@ static struct xsm_operations flask_ops = { .debug_keys = flask_debug_keys, .getcpuinfo = flask_getcpuinfo, .availheap = flask_availheap, + .get_pmstat = flask_get_pmstat, + .setpminfo = flask_setpminfo, + .pm_op = flask_pm_op, + .do_mca = flask_do_mca, .evtchn_unbound = flask_evtchn_unbound, .evtchn_interdomain = flask_evtchn_interdomain, @@ -1266,6 +1466,8 @@ static struct xsm_operations flask_ops = { .alloc_security_evtchn = flask_alloc_security_evtchn, .free_security_evtchn = flask_free_security_evtchn, + .get_pod_target = flask_get_pod_target, + .set_pod_target = flask_set_pod_target, .memory_adjust_reservation = flask_memory_adjust_reservation, .memory_stat_reservation = flask_memory_stat_reservation, .memory_pin_page = flask_memory_pin_page, @@ -1280,6 +1482,19 @@ static struct xsm_operations flask_ops = { .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, + .resource_plug_core = flask_resource_plug_core, + .resource_unplug_core = flask_resource_unplug_core, + .resource_plug_pci = flask_resource_plug_pci, + .resource_unplug_pci = flask_resource_unplug_pci, + .resource_setup_pci = flask_resource_setup_pci, + .resource_setup_gsi = flask_resource_setup_gsi, + .resource_setup_misc = flask_resource_setup_misc, + + .page_offline = flask_page_offline, + .lockprof = flask_lockprof, + .cpupool_op = flask_cpupool_op, + .sched_op = flask_sched_op, + .__do_xsm_op = do_flask_op, #ifdef CONFIG_X86 @@ -1293,6 +1508,8 @@ static struct xsm_operations flask_ops = { .hvm_set_pci_intx_level = flask_hvm_set_pci_intx_level, .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level, .hvm_set_pci_link_route = flask_hvm_set_pci_link_route, + .mem_event = flask_mem_event, + .mem_sharing = flask_mem_sharing, .apic = flask_apic, .xen_settime = flask_xen_settime, .memtype = flask_memtype, @@ -1310,10 +1527,12 @@ static struct xsm_operations flask_ops = { .update_va_mapping = flask_update_va_mapping, .add_to_physmap = flask_add_to_physmap, .sendtrigger = flask_sendtrigger, + .get_device_group = flask_get_device_group, .test_assign_device = flask_test_assign_device, .assign_device = flask_assign_device, .deassign_device = flask_deassign_device, .bind_pt_irq = flask_bind_pt_irq, + .unbind_pt_irq = flask_unbind_pt_irq, .pin_mem_cacheattr = flask_pin_mem_cacheattr, .ext_vcpucontext = flask_ext_vcpucontext, .vcpuextstate = flask_vcpuextstate, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index 56572a7..85cbffc 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -24,6 +24,11 @@ S_(SECCLASS_XEN, XEN__DEBUG, "debug") S_(SECCLASS_XEN, XEN__GETCPUINFO, "getcpuinfo") S_(SECCLASS_XEN, XEN__HEAP, "heap") + S_(SECCLASS_XEN, XEN__PM_OP, "pm_op") + S_(SECCLASS_XEN, XEN__MCA_OP, "mca_op") + S_(SECCLASS_XEN, XEN__LOCKPROF, "lockprof") + S_(SECCLASS_XEN, XEN__CPUPOOL_OP, "cpupool_op") + S_(SECCLASS_XEN, XEN__SCHED_OP, "sched_op") S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT, "setvcpucontext") S_(SECCLASS_DOMAIN, DOMAIN__PAUSE, "pause") S_(SECCLASS_DOMAIN, DOMAIN__UNPAUSE, "unpause") @@ -52,6 +57,9 @@ S_(SECCLASS_DOMAIN, DOMAIN__SETEXTVCPUCONTEXT, "setextvcpucontext") S_(SECCLASS_DOMAIN, DOMAIN__GETVCPUEXTSTATE, "getvcpuextstate") S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUEXTSTATE, "setvcpuextstate") + S_(SECCLASS_DOMAIN, DOMAIN__GETPODTARGET, "getpodtarget") + S_(SECCLASS_DOMAIN, DOMAIN__SETPODTARGET, "setpodtarget") + S_(SECCLASS_DOMAIN, DOMAIN__SET_MISC_INFO, "set_misc_info") S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc") S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") @@ -62,6 +70,9 @@ S_(SECCLASS_HVM, HVM__BIND_IRQ, "bind_irq") S_(SECCLASS_HVM, HVM__CACHEATTR, "cacheattr") S_(SECCLASS_HVM, HVM__TRACKDIRTYVRAM, "trackdirtyvram") + S_(SECCLASS_HVM, HVM__HVMCTL, "hvmctl") + S_(SECCLASS_HVM, HVM__MEM_EVENT, "mem_event") + S_(SECCLASS_HVM, HVM__MEM_SHARING, "mem_sharing") S_(SECCLASS_EVENT, EVENT__BIND, "bind") S_(SECCLASS_EVENT, EVENT__SEND, "send") S_(SECCLASS_EVENT, EVENT__STATUS, "status") @@ -103,6 +114,9 @@ S_(SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, "stat_device") S_(SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, "add_device") S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, "remove_device") + S_(SECCLASS_RESOURCE, RESOURCE__PLUG, "plug") + S_(SECCLASS_RESOURCE, RESOURCE__UNPLUG, "unplug") + S_(SECCLASS_RESOURCE, RESOURCE__SETUP, "setup") S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av") S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create") S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index 67511ad..9e55a86 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -24,6 +24,11 @@ #define XEN__DEBUG 0x00400000UL #define XEN__GETCPUINFO 0x00800000UL #define XEN__HEAP 0x01000000UL +#define XEN__PM_OP 0x02000000UL +#define XEN__MCA_OP 0x04000000UL +#define XEN__LOCKPROF 0x08000000UL +#define XEN__CPUPOOL_OP 0x10000000UL +#define XEN__SCHED_OP 0x20000000UL #define DOMAIN__SETVCPUCONTEXT 0x00000001UL #define DOMAIN__PAUSE 0x00000002UL @@ -53,6 +58,9 @@ #define DOMAIN__SETEXTVCPUCONTEXT 0x02000000UL #define DOMAIN__GETVCPUEXTSTATE 0x04000000UL #define DOMAIN__SETVCPUEXTSTATE 0x08000000UL +#define DOMAIN__GETPODTARGET 0x10000000UL +#define DOMAIN__SETPODTARGET 0x20000000UL +#define DOMAIN__SET_MISC_INFO 0x40000000UL #define HVM__SETHVMC 0x00000001UL #define HVM__GETHVMC 0x00000002UL @@ -64,6 +72,9 @@ #define HVM__BIND_IRQ 0x00000080UL #define HVM__CACHEATTR 0x00000100UL #define HVM__TRACKDIRTYVRAM 0x00000200UL +#define HVM__HVMCTL 0x00000400UL +#define HVM__MEM_EVENT 0x00000800UL +#define HVM__MEM_SHARING 0x00001000UL #define EVENT__BIND 0x00000001UL #define EVENT__SEND 0x00000002UL @@ -110,6 +121,9 @@ #define RESOURCE__STAT_DEVICE 0x00000200UL #define RESOURCE__ADD_DEVICE 0x00000400UL #define RESOURCE__REMOVE_DEVICE 0x00000800UL +#define RESOURCE__PLUG 0x00001000UL +#define RESOURCE__UNPLUG 0x00002000UL +#define RESOURCE__SETUP 0x00004000UL #define SECURITY__COMPUTE_AV 0x00000001UL #define SECURITY__COMPUTE_CREATE 0x00000002UL -- 1.7.7.4
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/dummy.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 126 insertions(+), 20 deletions(-) diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 7066dfb..a4accb8 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -89,6 +89,11 @@ static int dummy_set_target (struct domain *d, struct domain *e) return 0; } +static int dummy_domctl(struct domain *d, int cmd) +{ + return 0; +} + static int dummy_tbufcontrol (void) { return 0; @@ -139,11 +144,21 @@ static int dummy_get_pmstat (void) return 0; } +static int dummy_setpminfo (void) +{ + return 0; +} + static int dummy_pm_op (void) { return 0; } +static int dummy_do_mca (void) +{ + return 0; +} + static int dummy_availheap (void) { return 0; @@ -268,6 +283,77 @@ static void dummy_free_security_evtchn (struct evtchn *chn) return; } +static int dummy_test_assign_device (uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_assign_device (struct domain *d, uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_deassign_device (struct domain *d, uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_resource_plug_core (void) +{ + return 0; +} + +static int dummy_resource_unplug_core (void) +{ + return 0; +} + +static int dummy_resource_plug_pci (uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_resource_unplug_pci (uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_resource_setup_pci (uint32_t machine_bdf) +{ + return 0; +} + +static int dummy_resource_setup_gsi (int gsi) +{ + return 0; +} + +static int dummy_resource_setup_misc (void) +{ + return 0; +} + +static int dummy_page_offline (uint32_t cmd) +{ + return 0; +} + +static int dummy_lockprof (void) +{ + return 0; +} + +static int dummy_cpupool_op (void) +{ + return 0; +} + +static int dummy_sched_op (void) +{ + return 0; +} + + static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op) { return -ENOSYS; @@ -339,6 +425,21 @@ static int dummy_hvm_set_pci_link_route (struct domain *d) return 0; } +static int dummy_hvm_inject_msi (struct domain *d) +{ + return 0; +} + +static int dummy_mem_event (struct domain *d) +{ + return 0; +} + +static int dummy_mem_sharing (struct domain *d) +{ + return 0; +} + static int dummy_apic (struct domain *d, int cmd) { return 0; @@ -426,21 +527,6 @@ static int dummy_sendtrigger (struct domain *d) return 0; } -static int dummy_test_assign_device (uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_assign_device (struct domain *d, uint32_t machine_bdf) -{ - return 0; -} - -static int dummy_deassign_device (struct domain *d, uint32_t machine_bdf) -{ - return 0; -} - static int dummy_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind) { return 0; @@ -497,6 +583,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, getvcpuinfo); set_to_dummy_if_null(ops, domain_settime); set_to_dummy_if_null(ops, set_target); + set_to_dummy_if_null(ops, domctl); set_to_dummy_if_null(ops, tbufcontrol); set_to_dummy_if_null(ops, readconsole); set_to_dummy_if_null(ops, sched_id); @@ -506,9 +593,11 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, perfcontrol); set_to_dummy_if_null(ops, debug_keys); set_to_dummy_if_null(ops, getcpuinfo); - set_to_dummy_if_null(ops, pm_op); - set_to_dummy_if_null(ops, get_pmstat); set_to_dummy_if_null(ops, availheap); + set_to_dummy_if_null(ops, get_pmstat); + set_to_dummy_if_null(ops, setpminfo); + set_to_dummy_if_null(ops, pm_op); + set_to_dummy_if_null(ops, do_mca); set_to_dummy_if_null(ops, evtchn_unbound); set_to_dummy_if_null(ops, evtchn_interdomain); @@ -543,6 +632,23 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); + set_to_dummy_if_null(ops, test_assign_device); + set_to_dummy_if_null(ops, assign_device); + set_to_dummy_if_null(ops, deassign_device); + + set_to_dummy_if_null(ops, resource_plug_core); + set_to_dummy_if_null(ops, resource_unplug_core); + set_to_dummy_if_null(ops, resource_plug_pci); + set_to_dummy_if_null(ops, resource_unplug_pci); + set_to_dummy_if_null(ops, resource_setup_pci); + set_to_dummy_if_null(ops, resource_setup_gsi); + set_to_dummy_if_null(ops, resource_setup_misc); + + set_to_dummy_if_null(ops, page_offline); + set_to_dummy_if_null(ops, lockprof); + set_to_dummy_if_null(ops, cpupool_op); + set_to_dummy_if_null(ops, sched_op); + set_to_dummy_if_null(ops, __do_xsm_op); #ifdef CONFIG_X86 @@ -557,6 +663,9 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, hvm_set_pci_intx_level); set_to_dummy_if_null(ops, hvm_set_isa_irq_level); set_to_dummy_if_null(ops, hvm_set_pci_link_route); + set_to_dummy_if_null(ops, hvm_inject_msi); + set_to_dummy_if_null(ops, mem_event); + set_to_dummy_if_null(ops, mem_sharing); set_to_dummy_if_null(ops, apic); set_to_dummy_if_null(ops, xen_settime); set_to_dummy_if_null(ops, memtype); @@ -574,9 +683,6 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, update_va_mapping); set_to_dummy_if_null(ops, add_to_physmap); set_to_dummy_if_null(ops, sendtrigger); - set_to_dummy_if_null(ops, test_assign_device); - set_to_dummy_if_null(ops, assign_device); - set_to_dummy_if_null(ops, deassign_device); set_to_dummy_if_null(ops, bind_pt_irq); set_to_dummy_if_null(ops, pin_mem_cacheattr); set_to_dummy_if_null(ops, ext_vcpucontext); -- 1.7.7.4
Daniel De Graaf
2011-Dec-13 20:38 UTC
[PATCH 7/8] xsm: add checks on PCI configuration access
PCI configuration access is allowed to any privileged domain regardless of I/O port access restrictions; add XSM hooks for these accesses. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/traps.c | 26 ++++++++++++++++++++++---- xen/arch/x86/x86_64/mmconfig_64.c | 13 +++++++++++++ xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 8 ++++++++ xen/xsm/flask/hooks.c | 24 ++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 7f38ddc..2d585c8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -72,6 +72,7 @@ #include <asm/mc146818rtc.h> #include <asm/hpet.h> #include <public/arch-x86/cpuid.h> +#include <xsm/xsm.h> /* * opt_nmi: one of ''ignore'', ''dom0'', or ''fatal''. @@ -1680,6 +1681,21 @@ static int admin_io_okay( return ioports_access_permitted(v->domain, port, port + bytes - 1); } +static int pci_cfg_ok(struct domain *d, int write, int size) +{ + uint32_t machine_bdf; + uint16_t start, end; + if (!IS_PRIV(d)) + return 0; + + machine_bdf = (d->arch.pci_cf8 >> 8) & 0xFFFF; + start = d->arch.pci_cf8 & 0xFF; + end = start + size - 1; + if (xsm_pci_config_permission(d, machine_bdf, start, end, write)) + return 0; + return 1; +} + static uint32_t guest_io_read( unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) @@ -1726,12 +1742,13 @@ static uint32_t guest_io_read( size = 4; sub_data = v->domain->arch.pci_cf8; } - else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + else if ( (port & 0xfffc) == 0xcfc ) { size = min(bytes, 4 - (port & 3)); if ( size == 3 ) size = 2; - sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size); + if ( pci_cfg_ok(v->domain, 0, size) ) + sub_data = pci_conf_read(v->domain->arch.pci_cf8, port & 3, size); } if ( size == 4 ) @@ -1798,12 +1815,13 @@ static void guest_io_write( size = 4; v->domain->arch.pci_cf8 = data; } - else if ( ((port & 0xfffc) == 0xcfc) && IS_PRIV(v->domain) ) + else if ( (port & 0xfffc) == 0xcfc ) { size = min(bytes, 4 - (port & 3)); if ( size == 3 ) size = 2; - pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data); + if ( pci_cfg_ok(v->domain, 1, size) ) + pci_conf_write(v->domain->arch.pci_cf8, port & 3, size, data); } if ( size == 4 ) diff --git a/xen/arch/x86/x86_64/mmconfig_64.c b/xen/arch/x86/x86_64/mmconfig_64.c index 16d432e..f2e7fed 100644 --- a/xen/arch/x86/x86_64/mmconfig_64.c +++ b/xen/arch/x86/x86_64/mmconfig_64.c @@ -14,6 +14,7 @@ #include <xen/xmalloc.h> #include <xen/pci.h> #include <xen/pci_regs.h> +#include <xsm/xsm.h> #include "mmconfig.h" @@ -58,6 +59,7 @@ int pci_mmcfg_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { char __iomem *addr; + uint32_t mbdf; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) { @@ -65,6 +67,12 @@ err: *value = -1; return -EINVAL; } + mbdf = (seg << 16) | (bus << 8) | devfn; + if (xsm_pci_config_permission(current->domain, mbdf, reg, reg + len - 1, 0)) { + *value = -1; + return -EPERM; + } + addr = pci_dev_base(seg, bus, devfn); if (!addr) goto err; @@ -88,11 +96,16 @@ int pci_mmcfg_write(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 value) { char __iomem *addr; + uint32_t mbdf; /* Why do we have this when nobody checks it. How about a BUG()!? -AK */ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) return -EINVAL; + mbdf = (seg << 16) | (bus << 8) | devfn; + if (xsm_pci_config_permission(current->domain, mbdf, reg, reg + len - 1, 1)) + return -EPERM; + addr = pci_dev_base(seg, bus, devfn); if (!addr) return -EINVAL; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 0c7f248..df6cec2 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -113,6 +113,7 @@ struct xsm_operations { int (*schedop_shutdown) (struct domain *d1, struct domain *d2); 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 (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access); int (*get_device_group) (uint32_t machine_bdf); int (*test_assign_device) (uint32_t machine_bdf); @@ -473,6 +474,11 @@ static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e return xsm_call(iomem_permission(d, s, e, allow)); } +static inline int xsm_pci_config_permission (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) +{ + return xsm_call(pci_config_permission(d, machine_bdf, start, end, access)); +} + static inline int xsm_get_device_group(uint32_t machine_bdf) { return xsm_call(get_device_group(machine_bdf)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index a4accb8..4bbfbff 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -369,6 +369,13 @@ static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uin return 0; } +static int dummy_pci_config_permission (struct domain *d, uint32_t machine_bdf, + uint16_t start, uint16_t end, + uint8_t access) +{ + return 0; +} + #ifdef CONFIG_X86 static int dummy_shadow_control (struct domain *d, uint32_t op) { @@ -631,6 +638,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); + set_to_dummy_if_null(ops, pci_config_permission); set_to_dummy_if_null(ops, test_assign_device); set_to_dummy_if_null(ops, assign_device); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index efe52bb..0d35767 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -762,6 +762,29 @@ static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end return security_iterate_iomem_sids(start, end, _iomem_has_perm, &data); } +static int flask_pci_config_permission(struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access) +{ + u32 rsid; + int rc = -EPERM; + struct avc_audit_data ad; + struct domain_security_struct *ssec; + u32 perm = RESOURCE__USE; + + rc = security_device_sid(machine_bdf, &rsid); + if ( rc ) + return rc; + + /* Writes to the BARs count as setup */ + if ( access && (end >= 0x10 && start < 0x28) ) + perm = RESOURCE__SETUP; + + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long) machine_bdf; + ssec = d->ssid; + return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); + +} + static int flask_resource_plug_core(void) { struct domain_security_struct *ssec; @@ -1481,6 +1504,7 @@ static struct xsm_operations flask_ops = { .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, + .pci_config_permission = flask_pci_config_permission, .resource_plug_core = flask_resource_plug_core, .resource_unplug_core = flask_resource_unplug_core, -- 1.7.7.4
Daniel De Graaf
2011-Dec-13 20:38 UTC
[PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/man/xl.pod.1 | 38 ++++++++++++++++++++++---------------- 1 files changed, 22 insertions(+), 16 deletions(-) diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 index 5a39ae5..72196ee 100644 --- a/docs/man/xl.pod.1 +++ b/docs/man/xl.pod.1 @@ -197,10 +197,6 @@ I<filename> specified, without pausing the domain. The dump file will be written to a distribution specific directory for dump files. Such as: /var/lib/xen/dump or /var/xen/dump. -=item B<getenforce> - -Returns the current enforcing mode of the Flask Xen security module. - =item B<help> [I<--long>] Displays the short help message (i.e. common commands). @@ -303,10 +299,6 @@ less utilized than a high CPU workload. Consider yourself warned. =back -=item B<loadpolicy> I<policyfile> - -Loads a new policy int the Flask Xen security module. - =item B<mem-max> I<domain-id> I<mem> Specify the maximum amount of memory the domain is able to use, appending ''t'' @@ -397,10 +389,6 @@ Enable debug messages. =back -=item B<setenforce> I<1|0|Enforcing|Permissive> - -Sets the current enforcing mode of the Flask Xen security module - =item B<save> [I<OPTIONS>] I<domain-id> I<CheckpointFile> [I<ConfigFile>] Saves a running domain to a state file so that it can be restored @@ -997,6 +985,28 @@ Get information about how much freeable memory (MB) is in-use by tmem. =back +=head2 FLASK + +=over 4 + +=item B<getenforce> + +Determine if the FLASK security module is loaded and enforcing its policy. + +=item B<setenforce> I<1|0|Enforcing|Permissive> + +Enable or disable enforcing of the FLASK access controls. The default is +permissive and can be changed using the flask_enforcing option on the +hypervisor''s command line. + +=item B<loadpolicy> I<policy-file> + +Load FLASK policy from the given policy file. The initial policy is provided to +the hypervisor as a multiboot module; this command allows runtime updates to the +policy. Loading new security policy will reset runtime changes to device labels. + +=back + =head1 TO BE DOCUMENTED We need better documentation for: @@ -1007,10 +1017,6 @@ We need better documentation for: Trascendent Memory. -=item B<Flask> - -Xen Flask security module. - =back =head1 SEE ALSO -- 1.7.7.4
Ian Campbell
2011-Dec-14 10:41 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Tue, 2011-12-13 at 20:38 +0000, Daniel De Graaf wrote:> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>Thanks.> +=item B<getenforce> > +=item B<setenforce> I<1|0|Enforcing|Permissive> > +=item B<loadpolicy> I<policy-file>I think the intention was that commands be alphabetical within their section, although this section is so small I''m not sure it really matters. Ian.
Stefano Stabellini
2011-Dec-15 16:46 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Tue, 13 Dec 2011, Daniel De Graaf wrote:> +=head2 FLASK > + > +=over 4 > + > +=item B<getenforce> > + > +Determine if the FLASK security module is loaded and enforcing its policy. > + > +=item B<setenforce> I<1|0|Enforcing|Permissive> > + > +Enable or disable enforcing of the FLASK access controls. The default is > +permissive and can be changed using the flask_enforcing option on the > +hypervisor''s command line. > + > +=item B<loadpolicy> I<policy-file> > + > +Load FLASK policy from the given policy file. The initial policy is provided to > +the hypervisor as a multiboot module; this command allows runtime updates to the > +policy. Loading new security policy will reset runtime changes to device labels.Thanks for the patch! Since we are trying to improve the documentation for Xl, would you be up for writing a couple of more lines explaining why people might want to use XSM? In case there are some parameters to be used in the VM config file, could you please write a simple text file, like docs/misc/xl-network-configuration.markdown, describing which ones they are? Finally it would be great if you could submit, as a separate patch, an example policy file that we can keep under tools/examples/ or docs/misc for everybody to use.
Daniel De Graaf
2011-Dec-15 19:10 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On 12/15/2011 11:46 AM, Stefano Stabellini wrote:> On Tue, 13 Dec 2011, Daniel De Graaf wrote: >> +=head2 FLASK >> + >> +=over 4 >> + >> +=item B<getenforce> >> + >> +Determine if the FLASK security module is loaded and enforcing its policy. >> + >> +=item B<setenforce> I<1|0|Enforcing|Permissive> >> + >> +Enable or disable enforcing of the FLASK access controls. The default is >> +permissive and can be changed using the flask_enforcing option on the >> +hypervisor''s command line. >> + >> +=item B<loadpolicy> I<policy-file> >> + >> +Load FLASK policy from the given policy file. The initial policy is provided to >> +the hypervisor as a multiboot module; this command allows runtime updates to the >> +policy. Loading new security policy will reset runtime changes to device labels. > > Thanks for the patch! > Since we are trying to improve the documentation for Xl, would you be up > for writing a couple of more lines explaining why people might want to > use XSM?FLASK is a security framework that defines a mandatory access control policy providing fine-grained controls over Xen domains, allowing the policy writer to define what interactions between domains, devices, and the hypervisor are permitted. Some example of what you can do using XSM/FLASK: - Prevent two domains from communicating via event channels or grants - Control which domains can use device passthrough (and which devices) - Restrict or audit operations performed by privileged domains - Prevent a privileged domain from arbitrarily mapping pages from other domains Note that some of these examples require dom0 disaggregation to be useful, since the domain build process requires the ability to write to the new domain''s memory.> In case there are some parameters to be used in the VM config > file, could you please write a simple text file, like > docs/misc/xl-network-configuration.markdown, describing which ones they > are?There is only one domain configuration parameter (the security label), which I''m not sure is enough to justify its own file. If using the example policy, "seclabel=''system_u:system_r:domU_t''" would be used for PV domains, while "seclabel=''system_u:system_r:domHU_t''" would be used for HVM domains. A more complex policy may have a different type for each domain. It would be better to refer to existing SELinux documentation for an explanation of the meanings of system_u, system_r, domU_t, and possible MLS labels. For simple policies, the user and role portions of the label will be unused and will always be "system_u:system_r".> Finally it would be great if you could submit, as a separate patch, an > example policy file that we can keep under tools/examples/ or docs/misc > for everybody to use.There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te although it will likely require additional rules to be run in enforcing mode. The policy is not built as part of the normal build process, but it can be built by running "make -C tools/flask/policy". If using Fedora 16 (or systems with a checkpolicy version >24) the Makefile will need to be adjusted to produce policy version 24 which is the latest version supported by Xen. -- Daniel De Graaf National Security Agency
Konrad Rzeszutek Wilk
2011-Dec-15 20:56 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te > although it will likely require additional rules to be run in enforcing mode. > The policy is not built as part of the normal build process, but it can be > built by running "make -C tools/flask/policy". If using Fedora 16 (or systems > with a checkpolicy version >24) the Makefile will need to be adjusted to > produce policy version 24 which is the latest version supported by Xen.Is there a howto on how to use it for newbies? Or how to apply policies against a domain? Would it make sense to have that as part of the ''man xl'' ?
Rewrite the example policy to make it easier to understand and demonstrate some of the security goals that FLASK can enforce. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.if | 150 +++++++++++----------- tools/flask/policy/policy/modules/xen/xen.te | 180 ++++++++++++++----------- 2 files changed, 178 insertions(+), 152 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 1b50898..cd240d8 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -1,92 +1,96 @@ -############################################################################### -# -# create_domain(priv_dom, domain, channel) -# -################################################################################ -define(`create_domain'', ` - type $2, domain_type; - allow $1 $2:domain {create max_vcpus setdomainmaxmem - setaddrsize getdomaininfo hypercall - setvcpucontext scheduler unpause - getvcpuinfo getaddrsize getvcpuaffinity}; - allow $1 $2:shadow {enable}; - allow $1 $2:mmu {map_read map_write adjust physmap}; - allow $2 $2:mmu {adjust physmap}; - allow $1 $3:event {create}; -'') - -############################################################################### -# -# create_hvm_dom(priv_dom, domain, channel) -# -################################################################################ -define(`create_hvm_dom'', ` - create_domain($1, $2, $3) - allow $1 $2:hvm { setparam getparam cacheattr pciroute irqlevel pcilevel trackdirtyvram }; - allow $2 $2:hvm setparam; -'') +# Macro definitions for FLASK policy -############################################################################### -# -# create_pv_dom(priv_dom, domain, channel, iodomain) -# -################################################################################ -define(`create_pv_dom'', ` - create_domain($1, $2, $3) - allow $1 $2:mmu {memorymap pinpage}; - allow $2 $2:mmu {map_read map_write pinpage}; - allow $2 $4:mmu {map_read}; - - allow $2 $2:grant {query setup}; - allow $1 $2:grant {map_read unmap}; -'') ################################################################################ # -# manage_domain(priv_dom, domain) +# Domain creation and setup # ################################################################################ -define(`manage_domain'', ` - allow $1 $2:domain {pause destroy}; +# declare_domain(type) +# Declare a type as a domain type, and allow basic domain setup +define(`declare_domain'', ` + type $1, domain_type; + allow $1 $1:grant { query setup }; + allow $1 $1:mmu { adjust physmap map_read map_write stat pinpage }; + allow $1 $1:hvm { getparam setparam }; +'') + +# create_domain(priv, target) +# Allow a domain to be created +define(`create_domain'', ` + allow $1 $2:domain { create max_vcpus setdomainmaxmem setaddrsize + getdomaininfo hypercall setvcpucontext scheduler + unpause getvcpuinfo getvcpuextstate getaddrsize + getvcpuaffinity }; + allow $1 $2:security check_context; + allow $1 $2:shadow enable; + allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; + allow $1 $2:grant setup; + allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute setparam }; + allow $1 $2_$1_channel:event create; '') ################################################################################ # -# create_channel(caller, peer, channel) +# Inter-domain communication # ################################################################################ + +# create_channel(source, dest, chan-label) +# This allows an event channel to be created from domains with labels +# <source> to <dest> and will label it <chan-label> define(`create_channel'', ` type $3, event_type; type_transition $1 $2:event $3; - allow $1 $3:event {create}; - allow $3 $2:event {bind}; + allow $1 $3:event { create send status }; + allow $3 $2:event { bind }; '') -############################################################################### -# -# create_passthrough_resource(priv_dom, domain, resource) -# -############################################################################### -define(`create_passthrough_resource'', ` - type $3, resource_type; - allow $1 $2:resource {add remove}; - allow $1 ioport_t:resource {add_ioport use}; - allow $1 iomem_t:resource {add_iomem use}; - allow $1 irq_t:resource {add_irq use}; - allow $1 domio_t:mmu {map_read map_write}; - allow $2 domio_t:mmu {map_write}; - allow $2 irq_t:resource {use}; - allow $1 $3:resource {add_irq add_iomem add_ioport remove_irq remove_iomem remove_ioport use add_device remove_device}; - allow $2 $3:resource {use add_ioport add_iomem remove_ioport remove_iomem}; - allow $2 $3:mmu {map_read map_write}; + +# domain_event_comms(dom1, dom2) +# Allow two domain types to communicate using event channels +define(`domain_event_comms'', ` + create_channel($1, $2, $1_$2_channel) + create_channel($2, $1, $2_$1_channel) +'') + +# domain_comms(dom1, dom2) +# Allow two domain types to communicate using grants and event channels +define(`domain_comms'', ` + domain_event_comms($1, $2) + allow $1 $2:grant { map_read map_write copy unmap }; + allow $2 $1:grant { map_read map_write copy unmap }; +'') + +# domain_self_comms(domain) +# Allow a domain types to communicate with others of its type using grants +# and event channels (this includes event channels to DOMID_SELF) +define(`domain_self_comms'', ` + create_channel($1, $1, $1_self_channel) + allow $1 $1:grant { map_read map_write copy unmap }; '') -############################################################################### + +################################################################################ # -# create_hvm_resource(priv_dom, domain, resource) +# Device types and delegation (PCI passthrough) # -############################################################################### -define(`create_hvm_resource'', ` - type $3, resource_type; - allow $1 $2:resource {add remove}; - allow $1 $3:hvm {bind_irq}; - allow $1 $3:resource {stat_device add_device remove_device add_irq remove_irq add_iomem remove_iomem add_ioport remove_ioport}; - allow $2 $3:resource {use}; +################################################################################ + +# use_device(domain, device) +# Allow a device to be used by a domain +define(`use_device'', ` + allow $1 $2:resource use; + allow $1 $2:mmu { map_read map_write }; +'') + +# admin_device(domain, device) +# Allow a device to be used and delegated by a domain +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 }; + allow $1 $2:hvm bind_irq; + use_device($1, $2) +'') + +# delegate_devices(priv-domain, target-domain) +# Allow devices to be delegated +define(`delegate_devices'', ` + allow $1 $2:resource { add remove }; '') diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 1a7f29a..0fc31b5 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -1,21 +1,47 @@ +################################################################################ +# +# Attributes for types +# +# An attribute may be used in a rule as shorthand for all types with that +# attribute. +# +################################################################################ attribute xen_type; attribute domain_type; attribute resource_type; attribute event_type; attribute mls_priv; +################################################################################ +# +# Types for the initial SIDs +# +# These types are used internally for objects created during Xen startup or for +# devices that have not yet been labeled +# +################################################################################ + +# The hypervisor itself type xen_t, xen_type, domain_type, mls_priv; +# Domain 0 type dom0_t, domain_type, mls_priv; +# Untracked I/O memory (pseudo-domain) type domio_t, domain_type; +# Xen heap (pseudo-domain) type domxen_t, domain_type; +# Unlabeled objects type unlabeled_t, domain_type; +# The XSM/FLASK security server type security_t, domain_type; +# Unlabeled device resources +# Note: don''t allow access to these types directly; see below for how to label +# devices and use that label for allow rules type irq_t, resource_type; type ioport_t, resource_type; type iomem_t, resource_type; @@ -23,119 +49,115 @@ type device_t, resource_type; ################################################################################ # -# Boot the hypervisor and dom0 +# Rules required to boot the hypervisor and dom0 # ################################################################################ -allow dom0_t xen_t:xen {kexec readapic writeapic mtrr_read mtrr_add mtrr_del -scheduler physinfo heap quirk readconsole writeconsole settime microcode}; - -allow dom0_t domio_t:mmu {map_read map_write}; -allow dom0_t iomem_t:mmu {map_read map_write}; -allow dom0_t xen_t:mmu {memorymap}; - -allow dom0_t dom0_t:mmu {pinpage map_read map_write adjust updatemp}; -allow dom0_t dom0_t:grant {query setup}; -allow dom0_t dom0_t:domain {scheduler getdomaininfo getvcpuinfo getvcpuaffinity}; - -allow xen_t dom0_t:domain {create}; -allow xen_t dom0_t:resource {add remove}; -allow xen_t ioport_t:resource {add_ioport remove_ioport}; -allow dom0_t ioport_t:resource {use}; -allow xen_t iomem_t:resource {add_iomem remove_iomem}; -allow dom0_t iomem_t:resource {use}; -allow xen_t irq_t:resource {add_irq remove_irq}; -allow dom0_t irq_t:resource { add_irq remove_irq use}; +allow xen_t dom0_t:domain { create }; + +allow dom0_t xen_t:xen { kexec readapic writeapic mtrr_read mtrr_add mtrr_del + scheduler physinfo heap quirk readconsole writeconsole settime + microcode cpupool_op sched_op }; +allow dom0_t xen_t:mmu { memorymap }; +allow dom0_t security_t:security { check_context compute_av compute_create + compute_member load_policy compute_relabel compute_user setenforce + setbool setsecparam add_ocontext del_ocontext }; + +allow dom0_t dom0_t:domain { getdomaininfo getvcpuinfo getvcpuaffinity }; +allow dom0_t dom0_t:grant { query setup }; +allow dom0_t dom0_t:mmu { adjust physmap map_read map_write stat pinpage }; allow dom0_t dom0_t:resource { add remove }; -allow dom0_t xen_t:xen firmware; -allow dom0_t security_t:security {compute_av compute_create compute_member -check_context load_policy compute_relabel compute_user setenforce setbool -setsecparam add_ocontext del_ocontext}; +admin_device(dom0_t, device_t) +admin_device(dom0_t, irq_t) +admin_device(dom0_t, ioport_t) +admin_device(dom0_t, iomem_t) +allow dom0_t domio_t:mmu { map_read map_write }; -create_channel(dom0_t, dom0_t, evchn0-0_t) -allow dom0_t evchn0-0_t:event {send}; +domain_self_comms(dom0_t) -################################################################################ +auditallow dom0_t security_t:security { load_policy setenforce }; + +############################################################################### # -# Create and manage a domU w/ dom0 IO +# Domain creation # -################################################################################ -create_pv_dom(dom0_t, domU_t, evchnU-0_t, domio_t) +############################################################################### + +declare_domain(domU_t) +domain_self_comms(domU_t) +create_domain(dom0_t, domU_t) +domain_comms(dom0_t, domU_t) + +declare_domain(isolated_domU_t) +create_domain(dom0_t, isolated_domU_t) +domain_comms(dom0_t, isolated_domU_t) -create_channel(domU_t, domU_t, evchnU-U_t) -allow domU_t evchnU-U_t:event {send}; +############################################################################### +# +# Device delegation +# +############################################################################### -create_channel(dom0_t, domU_t, evchn0-U_t) -allow dom0_t evchn0-U_t:event {send}; +type nic_dev_t, resource_type; -create_channel(domU_t, dom0_t, evchnU-0_t) -allow domU_t evchnU-0_t:event {send}; +admin_device(dom0_t, nic_dev_t) +use_device(domU_t, nic_dev_t) -allow dom0_t dom0_t:event {send}; -allow dom0_t domU_t:grant {copy}; -allow domU_t domU_t:grant {copy}; +delegate_devices(dom0_t, domU_t) ############################################################################### # -# Create device labels +# Label devices for delegation +# +# The PCI, IRQ, memory, and I/O port ranges are hardware-specific. +# You may also use flask-label-pci to dynamically label devices on each boot. # ############################################################################### -# create device resources -#create_passthrough_resource(dom0_t, domU_t, nicP_t) -#create_hvm_resource(dom0_t, domHU_t, nicP_t) - # label e1000e nic -#pirqcon 33 system_u:object_r:nicP_t -#pirqcon 55 system_u:object_r:nicP_t -#iomemcon 0xfebe0-0xfebff system_u:object_r:nicP_t -#iomemcon 0xfebd9 system_u:object_r:nicP_t -#ioportcon 0xecc0-0xecdf system_u:object_r:nicP_t -#pcidevicecon 0xc800 system_u:object_r:nicP_t +#pirqcon 33 system_u:object_r:nic_dev_t +#pirqcon 55 system_u:object_r:nic_dev_t +#iomemcon 0xfebe0-0xfebff system_u:object_r:nic_dev_t +#iomemcon 0xfebd9 system_u:object_r:nic_dev_t +#ioportcon 0xecc0-0xecdf system_u:object_r:nic_dev_t +#pcidevicecon 0xc800 system_u:object_r:nic_dev_t # label e100 nic -#pirqcon 16 system_u:object_r:nicP_t -#iomemcon 0xfe5df system_u:object_r:nicP_t -#iomemcon 0xfe5e0-0xfe5ff system_u:object_r:nicP_t -#iomemcon 0xc2000-0xc200f system_u:object_r:nicP_t -#ioportcon 0xccc0-0xcd00 system_u:object_r:nicP_t +#pirqcon 16 system_u:object_r:nic_dev_t +#iomemcon 0xfe5df system_u:object_r:nic_dev_t +#iomemcon 0xfe5e0-0xfe5ff system_u:object_r:nic_dev_t +#iomemcon 0xc2000-0xc200f system_u:object_r:nic_dev_t +#ioportcon 0xccc0-0xcd00 system_u:object_r:nic_dev_t # label usb 1d.0-2 1d.7 -#pirqcon 23 system_u:object_r:nicP_t -#pirqcon 17 system_u:object_r:nicP_t -#pirqcon 18 system_u:object_r:nicP_t -#ioportcon 0xff80-0xFF9F system_u:object_r:nicP_t -#ioportcon 0xff60-0xff7f system_u:object_r:nicP_t -#ioportcon 0xff40-0xff5f system_u:object_r:nicP_t -#iomemcon 0xff980 system_u:object_r:nicP_t -#ioportcon 0xff00-0xff1f system_u:object_r:nicP_t - -manage_domain(dom0_t, domU_t) +#pirqcon 23 system_u:object_r:nic_dev_t +#pirqcon 17 system_u:object_r:nic_dev_t +#pirqcon 18 system_u:object_r:nic_dev_t +#ioportcon 0xff80-0xFF9F system_u:object_r:nic_dev_t +#ioportcon 0xff60-0xff7f system_u:object_r:nic_dev_t +#ioportcon 0xff40-0xff5f system_u:object_r:nic_dev_t +#iomemcon 0xff980 system_u:object_r:nic_dev_t +#ioportcon 0xff00-0xff1f system_u:object_r:nic_dev_t ################################################################################ # -# Create and manage an HVM domU w/ dom0 IO +# Constraints # ################################################################################ -create_hvm_dom(dom0_t, domHU_t, evchnHU-0_t) -allow dom0_t evchn0-HU_t:event {send}; -create_channel(domHU_t, domHU_t, evchnHU-HU_t) -allow domHU_t evchnU-U_t:event {send}; +# Domains must be declared using domain_type +neverallow * ~domain_type:domain create; -create_channel(dom0_t, domHU_t, evchn0-HU_t) -allow dom0_t evchn0-U_t:event {send}; +# Resources must be declared using resource_type +neverallow * ~resource_type:resource use; -create_channel(domHU_t, dom0_t, evchnHU-0_t) -allow domHU_t evchnU-0_t:event {send}; - -allow dom0_t dom0_t:event {send}; - -manage_domain(dom0_t, domHU_t) +# Events must use event_type (see create_channel for a template) +neverallow ~event_type *:event bind; +neverallow * ~event_type:event { create send status }; ################################################################################ # -# +# Labels for initial SIDs and system role # ################################################################################ sid xen gen_context(system_u:system_r:xen_t,s0) -- 1.7.7.4
Daniel De Graaf
2011-Dec-15 21:57 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On 12/15/2011 03:56 PM, Konrad Rzeszutek Wilk wrote:>> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te >> although it will likely require additional rules to be run in enforcing mode. >> The policy is not built as part of the normal build process, but it can be >> built by running "make -C tools/flask/policy". If using Fedora 16 (or systems >> with a checkpolicy version >24) the Makefile will need to be adjusted to >> produce policy version 24 which is the latest version supported by Xen. > > Is there a howto on how to use it for newbies? Or how to apply policies > against a domain? Would it make sense to have that as part of the ''man > xl'' ? >I just sent an updated example policy that demonstrates most of the features that can be used without dom0 disaggregation. It has two main types for domU: domU_t is a domain that can communicate with any other domU_t isolated_domU_t can only communicate with dom0 There is also a resource type for device passthrough, configured for domU_t. To label the PCI device 3:2.0 for passthrough, run: ./tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t I''m not sure this belongs in "man xl" except for a mention of how to set the security label of a newly created domain. There is already a docs/misc/xsm-flask.txt that explains a bit about the policy creation; this may need to be updated to better explain how to use FLASK. -- Daniel De Graaf National Security Agency
Daniel De Graaf writes ("[Xen-devel] [PATCH] flask/policy: Update example policy"):> Rewrite the example policy to make it easier to understand and > demonstrate some of the security goals that FLASK can enforce.Thanks. Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Ian Jackson
2011-Dec-20 18:21 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
Daniel De Graaf writes ("Re: [Xen-devel] [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands"):> FLASK is a security framework that defines a mandatory access control policy > providing fine-grained controls over Xen domains, allowing the policy writer > to define what interactions between domains, devices, and the hypervisor are > permitted. Some example of what you can do using XSM/FLASK: [etc]Perhaps you''d like to submit this excellent introductory text as a patch for inclusion somewhere under docs/ Thanks ? Ian.
Stefano Stabellini
2012-Jan-04 10:47 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Thu, 15 Dec 2011, Daniel De Graaf wrote:> On 12/15/2011 03:56 PM, Konrad Rzeszutek Wilk wrote: > >> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te > >> although it will likely require additional rules to be run in enforcing mode. > >> The policy is not built as part of the normal build process, but it can be > >> built by running "make -C tools/flask/policy". If using Fedora 16 (or systems > >> with a checkpolicy version >24) the Makefile will need to be adjusted to > >> produce policy version 24 which is the latest version supported by Xen. > > > > Is there a howto on how to use it for newbies? Or how to apply policies > > against a domain? Would it make sense to have that as part of the ''man > > xl'' ? > > > > I just sent an updated example policy that demonstrates most of the features > that can be used without dom0 disaggregation. It has two main types for domU: > > domU_t is a domain that can communicate with any other domU_t > isolated_domU_t can only communicate with dom0 > > There is also a resource type for device passthrough, configured for domU_t. > To label the PCI device 3:2.0 for passthrough, run: > > ./tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t > > I''m not sure this belongs in "man xl" except for a mention of how to set the > security label of a newly created domain. There is already a docs/misc/xsm-flask.txt > that explains a bit about the policy creation; this may need to be updated > to better explain how to use FLASK.It would be great to have a short introduction to flask in the xl man page. What do you think about the following? diff -r 50117a4d1a2c docs/man/xl.pod.1 --- a/docs/man/xl.pod.1 Mon Jan 02 12:43:07 2012 +0000 +++ b/docs/man/xl.pod.1 Wed Jan 04 10:46:47 2012 +0000 @@ -997,6 +997,20 @@ Get information about how much freeable =head2 FLASK +B<FLASK> is a security framework that defines a mandatory access control policy +providing fine-grained controls over Xen domains, allowing the policy writer +to define what interactions between domains, devices, and the hypervisor are +permitted. Some example of what you can do using XSM/FLASK: + - Prevent two domains from communicating via event channels or grants + - Control which domains can use device passthrough (and which devices) + - Restrict or audit operations performed by privileged domains + - Prevent a privileged domain from arbitrarily mapping pages from other + domains. + +See the following document for more details: + +L<http://xenbits.xen.org/docs/unstable/misc/xsm-flask.txt> + =over 4 =item B<getenforce> As you can see, I linked docs/misc/xsm-flask.txt from the xl man page, however xsm-flask.txt still references xend so it needs to be updated. Also it would be great to link the example policy too, but that one is not online because it is not under docs and it is not installed by default either. Maybe we need to move the example policy to docs? Or maybe it is best to install a copy of it to /etc/xen by default?
Daniel De Graaf
2012-Jan-04 15:03 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On 01/04/2012 05:47 AM, Stefano Stabellini wrote:> On Thu, 15 Dec 2011, Daniel De Graaf wrote: >> On 12/15/2011 03:56 PM, Konrad Rzeszutek Wilk wrote: >>>> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te >>>> although it will likely require additional rules to be run in enforcing mode. >>>> The policy is not built as part of the normal build process, but it can be >>>> built by running "make -C tools/flask/policy". If using Fedora 16 (or systems >>>> with a checkpolicy version >24) the Makefile will need to be adjusted to >>>> produce policy version 24 which is the latest version supported by Xen. >>> >>> Is there a howto on how to use it for newbies? Or how to apply policies >>> against a domain? Would it make sense to have that as part of the ''man >>> xl'' ? >>> >> >> I just sent an updated example policy that demonstrates most of the features >> that can be used without dom0 disaggregation. It has two main types for domU: >> >> domU_t is a domain that can communicate with any other domU_t >> isolated_domU_t can only communicate with dom0 >> >> There is also a resource type for device passthrough, configured for domU_t. >> To label the PCI device 3:2.0 for passthrough, run: >> >> ./tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t >> >> I''m not sure this belongs in "man xl" except for a mention of how to set the >> security label of a newly created domain. There is already a docs/misc/xsm-flask.txt >> that explains a bit about the policy creation; this may need to be updated >> to better explain how to use FLASK. > > It would be great to have a short introduction to flask in the xl man > page. What do you think about the following? > > > diff -r 50117a4d1a2c docs/man/xl.pod.1 > --- a/docs/man/xl.pod.1 Mon Jan 02 12:43:07 2012 +0000 > +++ b/docs/man/xl.pod.1 Wed Jan 04 10:46:47 2012 +0000 > @@ -997,6 +997,20 @@ Get information about how much freeable > > =head2 FLASK > > +B<FLASK> is a security framework that defines a mandatory access control policy > +providing fine-grained controls over Xen domains, allowing the policy writer > +to define what interactions between domains, devices, and the hypervisor are > +permitted. Some example of what you can do using XSM/FLASK: > + - Prevent two domains from communicating via event channels or grants > + - Control which domains can use device passthrough (and which devices) > + - Restrict or audit operations performed by privileged domains > + - Prevent a privileged domain from arbitrarily mapping pages from other > + domains. > + > +See the following document for more details: > + > +L<http://xenbits.xen.org/docs/unstable/misc/xsm-flask.txt> > + > =over 4 > > =item B<getenforce> > > > > As you can see, I linked docs/misc/xsm-flask.txt from the xl man page, > however xsm-flask.txt still references xend so it needs to be updated.This is a good introduction; I have an update to docs/misc/xsm-flask.txt that references xl and incorporates some of the changes in the example policy (will post momentarily).> Also it would be great to link the example policy too, but that one is > not online because it is not under docs and it is not installed by > default either. Maybe we need to move the example policy to docs? Or > maybe it is best to install a copy of it to /etc/xen by default?The example policy doesn''t really belong in docs because it needs to be compiled to be usable, and this depends on a number of other files (all files under tools/flask/policy/policy, to be exact). Compiling and installing FLASK policy during the normal build process (conditional on FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) would be the best solution. The policy must be installed to /boot, not /etc/xen, because the initial policy load happens prior to starting dom0. -- Daniel De Graaf National Security Agency
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/misc/xsm-flask.txt | 240 +++++++++++++++++-------------------------- tools/flask/policy/Makefile | 2 +- 2 files changed, 97 insertions(+), 145 deletions(-) diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt index 750bb28..2eb75d6 100644 --- a/docs/misc/xsm-flask.txt +++ b/docs/misc/xsm-flask.txt @@ -1,156 +1,97 @@ -These notes are compiled from xen-devel questions and postings that have occurred -since the inclusion of XSM. These notes are not intended to be definitive -documentation but should address many common problems that arise when -experimenting with XSM:FLASK. + ----------------------- + XSM/FLASK Configuration + ----------------------- -Xen XSM:FLASK configuration ---------------------------- +Xen provides a security framework called XSM, and FLASK is an implementation of +a security model using this framework (at the time of writing, it is the only +one). FLASK defines a mandatory access control policy providing fine-grained +controls over Xen domains, allowing the policy writer to define what +interactions between domains, devices, and the hypervisor are permitted. -1) cd xen-unstable.hg -2) edit Config.mk in the toplevel xen directory as follows: +Some examples of what FLASK can do: + - Prevent two domains from communicating via event channels or grants + - Control which domains can use device passthrough (and which devices) + - Restrict or audit operations performed by privileged domains + - Prevent a privileged domain from arbitrarily mapping pages from other domains - XSM_ENABLE ?= y - FLASK_ENABLE ?= y - -NB: Only one security module can be selected at a time. If no module is -selected, then the default DUMMY module will be enforced. The DUMMY module -only exercises the security framework and does not enforce any security -policies. Changing the security module selection will require recompiling xen. -These settings will also configure the corresponding toolchain support. - -3) make xen -4) make tools - - -Xen XSM:FLASK policy --------------------- - -These instructions will enable the configuration and build of the sample policy. -The sample policy provides the MINIMUM policy necessary to boot a -paravirtualized dom0 and create a pv or hvm domU. Many of the -default capabilities and usages supported by dom0/domU are disallowed by the -sample policy. Further, the policy is comprised of a limited number of types and -must be adjusted to meet the specific security goals of the installation. -Modification of the policy is straightforward and is covered in a later section. - -NB: The policy is not automatically built as part of the tool support because -of an external dependancy on the checkpolicy compiler. The FLASK policy uses -the same syntax and structure as SELinux and compiling the policy relies on -the SELinux policy toolchain. This toolchain is available under many -distributions as well as the following URL, - - http://userspace.selinuxproject.org/trac/wiki/Releases - -You will need at least libsepol and checkpolicy in order to compile a policy. +Some of these examples require dom0 disaggregation to be useful, since the +domain build process requires the ability to write to the new domain''s memory. -1) cd xen-unstable.hg/tools/flask/policy -2) make policy -3) make install -4) edit /etc/grub.conf, add a module line to the xen entry, - module /xenpolicy.24 +Setting up FLASK +---------------- -NB: The .24 suffix reflects the policy format version and may differ for your -system depending on the version of checkpolicy you used to build the policy. -At the time of this writing, policy version 24 is the highest version -supported by the latest checkpolicy release and by the Xen Flask module. -You can force the policy build to a specific policy version by uncommenting -the OUTPUT_POLICY= line in the policy Makefile and setting the value as -desired (to any version supported by the Xen Flask module, presently in the -range 15-24). Make sure that your module line above matches the actual -/xenpolicy.NN file that was created in /boot by the make install. - -5) reboot, and select the updated xen entry - -NB: The module entry can be inserted on any line after the xen kernel line. Typical -configurations use the last module entry or the module entry that immediately -follows the xen kernel entry. - -If you want to use the MLS policy, then set TYPE=xen-mls in the policy Makefile -before building the policy. Note that the MLS constraints in policy/mls -are incomplete and are only a sample. - -Xen configuration of xend -------------------------- +Xen must be compiled with XSM and FLASK enabled; by default, the security +framework is disabled. Edit Config.mk or the .config file to set XSM_ENABLE and +FLASK_ENABLE to "y"; this change requires a make clean and rebuild. -1) cd /etc/xen -2) edit xend-config.sxp -3) uncomment the line containing the key:value pair entry, +FLASK uses only one domain configuration parameter (seclabel) defining the +full security label of the newly created domain. If using the example policy, +"seclabel=''system_u:system_r:domU_t''" would be used for normal domains. For +simple policies including the example policy, the user and role portions of the +label are unused and will always be "system_u:system_r". Most of FLASK policy +consists of defining the interactions allowed between different types (domU_t +would be the type in this example); FLASK policy does not distinguish between +domains with the same type. This is the same format as used for SELinux +labeling; see http://selinuxproject.org for more details on the use of the user, +role, and optional MLS/MCS labels. - #(xsm_module_name dummy) +The FLASK security framework is mostly configured using a security policy file. +This policy file is not normally generated during the Xen build process because +it relies on the SELinux compiler "checkpolicy"; run -4) change the value entry to ''flask'' + make -C tools/flask/policy - (xsm_module_name flask) +to compile the example policy included with Xen. The policy is generated from +definition files under this directory. When creating or modifying security +policy, most modifications will be made to the xen type enforcement (.te) file +tools/flask/policy/policy/modules/xen/xen.te or the macro definitions in xen.if. +The XSM policy file needs to be copied to /boot and loaded as a module by grub. +The exact position of the module does not matter as long as it is after the Xen +kernel; it is normally placed either just above the dom0 kernel or at the end. +Once dom0 is running, the policy can be reloaded using "xl loadpolicy". -5) restart xend +The example policy included with Xen demonstrates most of the features of FLASK +that can be used without dom0 disaggregation. It has two main types for domUs: -Creating policy controlled domains ----------------------------------- + - domU_t is a domain that can communicate with any other domU_t + - isolated_domU_t can only communicate with dom0 -2) Edit the domain config file and add the following entry for a pv guest, +More types can be added to allow groups of domains to communicate without +allowing communication between groups, or only between certain groups. - access_control = ["policy=,label=system_u:system_r:domU_t"] +The example policy also includes a resource type (nic_dev_t) for device +passthrough, configured to allow use by domU_t. To label the PCI device 3:2.0 +for passthrough, run: -or add the following entry for a hvm guest: + tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t - access_control = ["policy=,label=system_u:system_r:domHU_t"] +This command must be rerun on each boot or after any policy reload. -NB: The ''policy'' field is not used by XSM:FLASK. The ''label'' must exist in the -loaded policy. ''system_u:system_r:domU_t'' is one of the existing labels from -the sample policy and shown for example purposes. +The example policy was only tested with simple domain creation and may be +missing rules allowing accesses by dom0 or domU when a number of hypervisor +features are used. When first loading or writing a policy, you should run FLASK +in permissive mode (the default) and check the Xen logs (xl dmesg) for AVC +denials before using it in enforcing mode (flask_enforcing=1 on the command +line, or xl setenforce). -If you enabled the MLS policy, then append a MLS level (e.g. s0:c0) to the -labels, e.g.: - access_control = ["policy=,label=system_u:system_r:domU_t:s0:c0"] +MLS/MCS policy +-------------- -2) Create the domain using the ''xm create'' command. -3) Use the ''xm list --label'' command to list the running -domains and their labels. - -Updating the XSM:FLASK policy ------------------------------ - -It is recommended that the XSM:FLASK policy be tailored to meet the specific -security goals of the platform. The policy is tailored by editing the xen.if and xen.te files in the ''policy'' subdirectory. - -1) cd xen-unstable.hg/tools/flask/policy -2) edit policy/modules/xen/xen.* - make changes to support platform security goals. -3) make policy -4) make install -5) reboot - -Alternatively, one may reload the policy using the ''flask_loadpolicy'' tool -installed by the xen tools. - -1) flask_loadpolicy policy.24 - -NB: The sample policy permits policy reloads as well as general manipulation of -the Flask security server only from dom0. The policy can be tailored further to -restrict policy reloads and other manipulations to boot-time only, by removing -the corresponding statements from the policy. - -Enforcing the XSM:FLASK policy ------------------------------- - -By default, XSM:FLASK is compiled and installed in permissive mode. This -configuration will allow an XSM:FLASK system to start in enforcing mode. +If you want to use the MLS policy, then set TYPE=xen-mls in the policy Makefile +before building the policy. Note that the MLS constraints in policy/mls +are incomplete and are only a sample. -1) edit /etc/grub.conf -2) append the parameter ''flask_enforcing=1'' to the xen kernel line. -3) reboot, and select the updated xen entry AVC denials ----------- -XSM:Flask will emit avc: denied messages when a permission is denied -by the policy, just like SELinux. For example, if you were to use -system_u:system_r:domU_t label for a hvm guest (rather than -system_u:system_r:domHU_t), you would get a set of denials upon xm -create: +XSM:Flask will emit avc: denied messages when a permission is denied by the +policy, just like SELinux. For example, if the HVM rules are removed from the +declare_domain and create_domain interfaces: -# xm dmesg | grep avc +# xl dmesg | grep avc (XEN) avc: denied { setparam } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm (XEN) avc: denied { getparam } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm (XEN) avc: denied { irqlevel } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm @@ -160,21 +101,29 @@ create: (XEN) avc: denied { pcilevel } for domid=0 scontext=system_u:system_r:dom0_t tcontext=system_u:system_r:domU_t tclass=hvm Existing SELinux tools such as audit2allow can be applied to these denials, e.g. -xm dmesg | audit2allow +xl dmesg | audit2allow The generated allow rules can then be fed back into the policy by adding them to xen.te, although manual review is advised and will -often lead to adding parameterized rules to the interfaces in xen.if +often lead to adding parameterized rules to the interfaces in xen.if to address the general case. -Device Policy -------------- -Flask is capable of labeling devices and enforcing policies associated with -them. To enable this functionality the latest version of checkpolicy -(>= 2.0.20) and libsepol (>=2.0.39) will be needed in order to compile it. To -enable the building of the new policies the following changes will need to be -done to tools/flask/policy/Makefile. +Device Labeling in Policy +------------------------- + +FLASK is capable of labeling devices and enforcing policies associated with +them. There are two methods to label devices: dynamic labeling using +flask-label-pci or similar tools run in dom0, or static labeling defined in +policy. Static labeling will make security policy machine-specific and may +prevent the system from booting after any hardware changes (adding PCI cards, +memory, or even changing certain BIOS settings). Dynamic labeling requires that +the domain performing the labeling be trusted to label all the devices in the +system properly. + +To enable static device labeling, a checkpolicy >= 2.0.20 and libsepol >=2.0.39 +are required. The policy Makefile (tools/flask/policy/Makefile) must also be +changed as follows: ######################################## # @@ -197,7 +146,7 @@ $(LOADPATH): policy.conf # $(QUIET) $(CHECKPOLICY) -t Xen $^ -o $@ (Uncomment this line) -Pirqs, PCI devices, I/O memory and ports can all be labeled. There are +IRQs, PCI devices, I/O memory and ports can all be labeled. There are commented out lines in xen.te policy for examples on how to label devices. Device Labeling @@ -223,13 +172,16 @@ iomemcon 0xfebd9 system_u:object_r:nicP_t ioportcon 0xecc0-0xecdf system_u:object_r:nicP_t pcidevicecon 0xc800 system_u:object_r:nicP_t -Labeling of the PCI device is tricky since there is no output in lspci that -makes the information easily available. The easiest way to obtain the -information is to look at the avc denial line for the correct hex value. +The PCI device label must be computed as the 32-bit SBDF number for the PCI +device. It the PCI device is aaaa:bb:cc.d or bb:cc.d, then the SBDF can be +calculated using: + SBDF = (a << 16) | (b << 8) | (c << 3) | d -(XEN) avc: denied { add_device } for domid=0 device=0xc800 <--- -scontext=system_u:system_r:dom0_t tcontext=system_u:object_r:device_t -tclass=resource +The AVC denials for IRQs, memory, ports, and PCI devices will normally contain +the ranges being denied to more easily determine what resources are required. +When running in permissive mode, only the first denial of a given +source/destination is printed to the log, so labeling devices using this method +may require multiple passes to find all required ranges. Additional notes on XSM:FLASK ----------------------------- @@ -242,7 +194,7 @@ Additional notes on XSM:FLASK platform to boot in permissive mode which means that the policy is loaded but not enforced. This mode is often helpful for developing new systems and policies as the policy violations are reported on the xen console and - may be viewed in dom0 through ''xm dmesg''. + may be viewed in dom0 through ''xl dmesg''. To boot the platform into enforcing mode, which means that the policy is loaded and enforced, append ''flask_enforcing=1'' on the grub line. diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile index e39f076..a27c813 100644 --- a/tools/flask/policy/Makefile +++ b/tools/flask/policy/Makefile @@ -20,7 +20,7 @@ # By default, checkpolicy will create the highest # version policy it supports. Setting this will # override the version. -# OUTPUT_POLICY = 24 +OUTPUT_POLICY = 24 # Policy Type # xen -- 1.7.7.5
Daniel De Graaf
2012-Jan-04 15:05 UTC
[PATCH 2/2] flask/policy: add missing manage_domain rules
The updated example policy did not include rules to allow managing the created domains (pause, unpause, destroy); allow these actions. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.if | 7 +++++++ tools/flask/policy/policy/modules/xen/xen.te | 2 ++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index cd240d8..3065718 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -29,6 +29,13 @@ define(`create_domain'', ` allow $1 $2_$1_channel:event create; '') +# manage_domain(priv, target) +# Allow managing a running domain +define(`manage_domain'', ` + allow $1 $2:domain { getdomaininfo getvcpuinfo getvcpuaffinity + getaddrsize pause unpause trigger shutdown destroy + setvcpuaffinity setdomainmaxmem }; +'') ################################################################################ # # Inter-domain communication diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 0fc31b5..c5e0883 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -86,10 +86,12 @@ auditallow dom0_t security_t:security { load_policy setenforce }; declare_domain(domU_t) domain_self_comms(domU_t) create_domain(dom0_t, domU_t) +manage_domain(dom0_t, domU_t) domain_comms(dom0_t, domU_t) declare_domain(isolated_domU_t) create_domain(dom0_t, isolated_domU_t) +manage_domain(dom0_t, isolated_domU_t) domain_comms(dom0_t, isolated_domU_t) ############################################################################### -- 1.7.7.5
Ian Campbell
2012-Jan-04 16:26 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Wed, 2012-01-04 at 15:03 +0000, Daniel De Graaf wrote:> On 01/04/2012 05:47 AM, Stefano Stabellini wrote: > > On Thu, 15 Dec 2011, Daniel De Graaf wrote: > >> On 12/15/2011 03:56 PM, Konrad Rzeszutek Wilk wrote: > >>>> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te > >>>> although it will likely require additional rules to be run in enforcing mode. > >>>> The policy is not built as part of the normal build process, but it can be > >>>> built by running "make -C tools/flask/policy". If using Fedora 16 (or systems > >>>> with a checkpolicy version >24) the Makefile will need to be adjusted to > >>>> produce policy version 24 which is the latest version supported by Xen. > >>> > >>> Is there a howto on how to use it for newbies? Or how to apply policies > >>> against a domain? Would it make sense to have that as part of the ''man > >>> xl'' ? > >>> > >> > >> I just sent an updated example policy that demonstrates most of the features > >> that can be used without dom0 disaggregation. It has two main types for domU: > >> > >> domU_t is a domain that can communicate with any other domU_t > >> isolated_domU_t can only communicate with dom0 > >> > >> There is also a resource type for device passthrough, configured for domU_t. > >> To label the PCI device 3:2.0 for passthrough, run: > >> > >> ./tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t > >> > >> I''m not sure this belongs in "man xl" except for a mention of how to set the > >> security label of a newly created domain. There is already a docs/misc/xsm-flask.txt > >> that explains a bit about the policy creation; this may need to be updated > >> to better explain how to use FLASK. > > > > It would be great to have a short introduction to flask in the xl man > > page. What do you think about the following? > > > > > > diff -r 50117a4d1a2c docs/man/xl.pod.1 > > --- a/docs/man/xl.pod.1 Mon Jan 02 12:43:07 2012 +0000 > > +++ b/docs/man/xl.pod.1 Wed Jan 04 10:46:47 2012 +0000 > > @@ -997,6 +997,20 @@ Get information about how much freeable > > > > =head2 FLASK > > > > +B<FLASK> is a security framework that defines a mandatory access control policy > > +providing fine-grained controls over Xen domains, allowing the policy writer > > +to define what interactions between domains, devices, and the hypervisor are > > +permitted. Some example of what you can do using XSM/FLASK: > > + - Prevent two domains from communicating via event channels or grants > > + - Control which domains can use device passthrough (and which devices) > > + - Restrict or audit operations performed by privileged domains > > + - Prevent a privileged domain from arbitrarily mapping pages from other > > + domains. > > + > > +See the following document for more details: > > + > > +L<http://xenbits.xen.org/docs/unstable/misc/xsm-flask.txt> > > + > > =over 4 > > > > =item B<getenforce> > > > > > > > > As you can see, I linked docs/misc/xsm-flask.txt from the xl man page, > > however xsm-flask.txt still references xend so it needs to be updated. > > This is a good introduction; I have an update to docs/misc/xsm-flask.txt > that references xl and incorporates some of the changes in the example > policy (will post momentarily). > > > Also it would be great to link the example policy too, but that one is > > not online because it is not under docs and it is not installed by > > default either. Maybe we need to move the example policy to docs? Or > > maybe it is best to install a copy of it to /etc/xen by default? > > The example policy doesn''t really belong in docs because it needs to be > compiled to be usable,I think Stefano was referring to having an online copy for reference. I think it should be ok to have "make -C docs html" (& txt etc) pickup the source files from tools/flash/policy and export them, this would mean they would show up on xenbits[0] automatically. Unless the policy files aren''t really suitable for that?> and this depends on a number of other files (all > files under tools/flask/policy/policy, to be exact). Compiling and > installing FLASK policy during the normal build process (conditional on > FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?)I think that makes sense right now. When we switch to autoconf this is the sort of thing we can/should autodetect. Ian. [0] at http://xenbits.xen.org/docs/unstable/> would be the best solution. The policy must be installed to /boot, not > /etc/xen, because the initial policy load happens prior to starting dom0. >
Stefano Stabellini
2012-Jan-04 16:49 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Wed, 4 Jan 2012, Daniel De Graaf wrote:> On 01/04/2012 05:47 AM, Stefano Stabellini wrote: > > On Thu, 15 Dec 2011, Daniel De Graaf wrote: > >> On 12/15/2011 03:56 PM, Konrad Rzeszutek Wilk wrote: > >>>> There is already an example policy file in tools/flask/policy/policy/modules/xen/xen.te > >>>> although it will likely require additional rules to be run in enforcing mode. > >>>> The policy is not built as part of the normal build process, but it can be > >>>> built by running "make -C tools/flask/policy". If using Fedora 16 (or systems > >>>> with a checkpolicy version >24) the Makefile will need to be adjusted to > >>>> produce policy version 24 which is the latest version supported by Xen. > >>> > >>> Is there a howto on how to use it for newbies? Or how to apply policies > >>> against a domain? Would it make sense to have that as part of the ''man > >>> xl'' ? > >>> > >> > >> I just sent an updated example policy that demonstrates most of the features > >> that can be used without dom0 disaggregation. It has two main types for domU: > >> > >> domU_t is a domain that can communicate with any other domU_t > >> isolated_domU_t can only communicate with dom0 > >> > >> There is also a resource type for device passthrough, configured for domU_t. > >> To label the PCI device 3:2.0 for passthrough, run: > >> > >> ./tools/flask/utils/flask-label-pci 0000:03:02.0 system_u:object_r:nic_dev_t > >> > >> I''m not sure this belongs in "man xl" except for a mention of how to set the > >> security label of a newly created domain. There is already a docs/misc/xsm-flask.txt > >> that explains a bit about the policy creation; this may need to be updated > >> to better explain how to use FLASK. > > > > It would be great to have a short introduction to flask in the xl man > > page. What do you think about the following? > > > > > > diff -r 50117a4d1a2c docs/man/xl.pod.1 > > --- a/docs/man/xl.pod.1 Mon Jan 02 12:43:07 2012 +0000 > > +++ b/docs/man/xl.pod.1 Wed Jan 04 10:46:47 2012 +0000 > > @@ -997,6 +997,20 @@ Get information about how much freeable > > > > =head2 FLASK > > > > +B<FLASK> is a security framework that defines a mandatory access control policy > > +providing fine-grained controls over Xen domains, allowing the policy writer > > +to define what interactions between domains, devices, and the hypervisor are > > +permitted. Some example of what you can do using XSM/FLASK: > > + - Prevent two domains from communicating via event channels or grants > > + - Control which domains can use device passthrough (and which devices) > > + - Restrict or audit operations performed by privileged domains > > + - Prevent a privileged domain from arbitrarily mapping pages from other > > + domains. > > + > > +See the following document for more details: > > + > > +L<http://xenbits.xen.org/docs/unstable/misc/xsm-flask.txt> > > + > > =over 4 > > > > =item B<getenforce> > > > > > > > > As you can see, I linked docs/misc/xsm-flask.txt from the xl man page, > > however xsm-flask.txt still references xend so it needs to be updated. > > This is a good introduction; I have an update to docs/misc/xsm-flask.txt > that references xl and incorporates some of the changes in the example > policy (will post momentarily).Great, I''ll send it as a separate patch.> > Also it would be great to link the example policy too, but that one is > > not online because it is not under docs and it is not installed by > > default either. Maybe we need to move the example policy to docs? Or > > maybe it is best to install a copy of it to /etc/xen by default? > > The example policy doesn''t really belong in docs because it needs to be > compiled to be usable, and this depends on a number of other files (all > files under tools/flask/policy/policy, to be exact). Compiling and > installing FLASK policy during the normal build process (conditional on > FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) > would be the best solution. The policy must be installed to /boot, not > /etc/xen, because the initial policy load happens prior to starting dom0.Like Ian said, I meant having the policy somewhere online where can be linked. However we only publish on xenbits what we have under docs ATM. It is unfortunate that the policy needs FLASK_ENABLE to be compiled because I am pretty sure that the automated build system that produces the docs that end up online does not support that option right now.
Ian Campbell
2012-Jan-04 16:54 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Wed, 2012-01-04 at 16:49 +0000, Stefano Stabellini wrote:> On Wed, 4 Jan 2012, Daniel De Graaf wrote: > > The example policy doesn''t really belong in docs because it needs to be > > compiled to be usable, and this depends on a number of other files (all > > files under tools/flask/policy/policy, to be exact). Compiling and > > installing FLASK policy during the normal build process (conditional on > > FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) > > would be the best solution. The policy must be installed to /boot, not > > /etc/xen, because the initial policy load happens prior to starting dom0. > > Like Ian said, I meant having the policy somewhere online where can be > linked. However we only publish on xenbits what we have under docs ATM. > It is unfortunate that the policy needs FLASK_ENABLE to be compiled > because I am pretty sure that the automated build system that produces > the docs that end up online does not support that option right now.Publishing the docs in this manner wouldn''t require FLASK_ENABLE since it doesn''t need any tools, just "cp". Unless I''ve totally got the wrong end of the stick and the policy needs processing before you can even usefully read it? Ian.
Daniel De Graaf
2012-Jan-04 18:28 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On 01/04/2012 11:54 AM, Ian Campbell wrote:> On Wed, 2012-01-04 at 16:49 +0000, Stefano Stabellini wrote: >> On Wed, 4 Jan 2012, Daniel De Graaf wrote: >>> The example policy doesn''t really belong in docs because it needs to be >>> compiled to be usable, and this depends on a number of other files (all >>> files under tools/flask/policy/policy, to be exact). Compiling and >>> installing FLASK policy during the normal build process (conditional on >>> FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) >>> would be the best solution. The policy must be installed to /boot, not >>> /etc/xen, because the initial policy load happens prior to starting dom0. >> >> Like Ian said, I meant having the policy somewhere online where can be >> linked. However we only publish on xenbits what we have under docs ATM. >> It is unfortunate that the policy needs FLASK_ENABLE to be compiled >> because I am pretty sure that the automated build system that produces >> the docs that end up online does not support that option right now. > > Publishing the docs in this manner wouldn''t require FLASK_ENABLE since > it doesn''t need any tools, just "cp". Unless I''ve totally got the wrong > end of the stick and the policy needs processing before you can even > usefully read it? > > Ian. >You can read the policy files as-is; the xen.te and xen.if files contain most of what you would want to inspect. However, this is similar to reading shell scripts or other source files, which is not what I would expect from files copied into a docs folder. There are some tools for searching and understanding SELinux policy such as sesearch that work either on the binary policy file or on the macro-expanded policy.conf. Building policy.conf only requires m4, which is already required for bison as part of Xen''s build process. This file is much less readable by humans, however, since it is the output of macro expansion. Also: the policy currently isn''t built automatically even if FLASK_ENABLE=y; this is something that I think should be changed although I will wait to post a patch until we''ve decided what parts of the output should be used. -- Daniel De Graaf National Security Agency
Ian Campbell
2012-Jan-05 08:48 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Wed, 2012-01-04 at 18:28 +0000, Daniel De Graaf wrote:> On 01/04/2012 11:54 AM, Ian Campbell wrote: > > On Wed, 2012-01-04 at 16:49 +0000, Stefano Stabellini wrote: > >> On Wed, 4 Jan 2012, Daniel De Graaf wrote: > >>> The example policy doesn''t really belong in docs because it needs to be > >>> compiled to be usable, and this depends on a number of other files (all > >>> files under tools/flask/policy/policy, to be exact). Compiling and > >>> installing FLASK policy during the normal build process (conditional on > >>> FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) > >>> would be the best solution. The policy must be installed to /boot, not > >>> /etc/xen, because the initial policy load happens prior to starting dom0. > >> > >> Like Ian said, I meant having the policy somewhere online where can be > >> linked. However we only publish on xenbits what we have under docs ATM. > >> It is unfortunate that the policy needs FLASK_ENABLE to be compiled > >> because I am pretty sure that the automated build system that produces > >> the docs that end up online does not support that option right now. > > > > Publishing the docs in this manner wouldn''t require FLASK_ENABLE since > > it doesn''t need any tools, just "cp". Unless I''ve totally got the wrong > > end of the stick and the policy needs processing before you can even > > usefully read it? > > > > Ian. > > > > You can read the policy files as-is; the xen.te and xen.if files contain > most of what you would want to inspect. However, this is similar to reading > shell scripts or other source files, which is not what I would expect from > files copied into a docs folder.In that case I think the best approach would be to reference the file via the mercurial webterface e.g. http://xenbits.xen.org/hg/xen-unstable.hg/file/tip/tools/flask/policy/policy/modules/xen/xen.te> There are some tools for searching and understanding SELinux policy such as > sesearch that work either on the binary policy file or on the macro-expanded > policy.conf. Building policy.conf only requires m4, which is already required > for bison as part of Xen''s build process. This file is much less readable by > humans, however, since it is the output of macro expansion.Doesn''t sound like something that it would be useful to publish, but does sound very useful if you''ve actually got the flask tools installed etc.> Also: the policy currently isn''t built automatically even if FLASK_ENABLE=y; > this is something that I think should be changed although I will wait to post > a patch until we''ve decided what parts of the output should be used.It sounds like we don''t need to use any parts but in any case we may as well arrange for it to be built and worry about any docs usage of it later. Ian.
Stefano Stabellini
2012-Jan-05 11:19 UTC
Re: [PATCH 8/8] xl.pod.1: improve documentation of FLASK commands
On Thu, 5 Jan 2012, Ian Campbell wrote:> On Wed, 2012-01-04 at 18:28 +0000, Daniel De Graaf wrote: > > On 01/04/2012 11:54 AM, Ian Campbell wrote: > > > On Wed, 2012-01-04 at 16:49 +0000, Stefano Stabellini wrote: > > >> On Wed, 4 Jan 2012, Daniel De Graaf wrote: > > >>> The example policy doesn''t really belong in docs because it needs to be > > >>> compiled to be usable, and this depends on a number of other files (all > > >>> files under tools/flask/policy/policy, to be exact). Compiling and > > >>> installing FLASK policy during the normal build process (conditional on > > >>> FLASK_ENABLE to avoid adding SELinux build tools to build dependencies?) > > >>> would be the best solution. The policy must be installed to /boot, not > > >>> /etc/xen, because the initial policy load happens prior to starting dom0. > > >> > > >> Like Ian said, I meant having the policy somewhere online where can be > > >> linked. However we only publish on xenbits what we have under docs ATM. > > >> It is unfortunate that the policy needs FLASK_ENABLE to be compiled > > >> because I am pretty sure that the automated build system that produces > > >> the docs that end up online does not support that option right now. > > > > > > Publishing the docs in this manner wouldn''t require FLASK_ENABLE since > > > it doesn''t need any tools, just "cp". Unless I''ve totally got the wrong > > > end of the stick and the policy needs processing before you can even > > > usefully read it? > > > > > > Ian. > > > > > > > You can read the policy files as-is; the xen.te and xen.if files contain > > most of what you would want to inspect. However, this is similar to reading > > shell scripts or other source files, which is not what I would expect from > > files copied into a docs folder. > > In that case I think the best approach would be to reference the file > via the mercurial webterface e.g. > http://xenbits.xen.org/hg/xen-unstable.hg/file/tip/tools/flask/policy/policy/modules/xen/xen.te > > > There are some tools for searching and understanding SELinux policy such as > > sesearch that work either on the binary policy file or on the macro-expanded > > policy.conf. Building policy.conf only requires m4, which is already required > > for bison as part of Xen''s build process. This file is much less readable by > > humans, however, since it is the output of macro expansion. > > Doesn''t sound like something that it would be useful to publish, but > does sound very useful if you''ve actually got the flask tools installed > etc. > > > Also: the policy currently isn''t built automatically even if FLASK_ENABLE=y; > > this is something that I think should be changed although I will wait to post > > a patch until we''ve decided what parts of the output should be used. > > It sounds like we don''t need to use any parts but in any case we may as > well arrange for it to be built and worry about any docs usage of it > later.Yeah, if we build it when FLASK_ENABLE=y at least we could simplify the "Xen XSM:FLASK policy" subchapter and we could say in the xl manpage that the user should be able to find a ready to use policy named "xenpolicy" under the /boot directory.
Daniel De Graaf writes ("[Xen-devel] [PATCH 1/2] docs: Update xsm-flask documentation"):> diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txtI''ve applied these two (the docs, and the policy update). Thanks, Ian.