This series is mostly cleanup and fixing bugs that have crept in; see individual patch descriptions for details. In their present state, these patches require a recompile of existing XSM policy due to the changes in initial SIDs and permissions. If backwards compatability with older policy (or newer policy used with older hypervisors) is needed, the definitions for old permissions could be left in by reverting the header file changes in #2 and not applying #7. [PATCH 1/8] flask: Fix policy build with new checkpolicy [PATCH 2/8] xsm: remove unused xsm_assign_vector check [PATCH 3/8] xsm: Revert "Fix xsm_mmu_* and xsm_update_va_mapping [PATCH 4/8] xsm: always allow setting non-present PTEs [PATCH 5/8] xsm: Expand I/O resource hooks [PATCH 6/8] xsm: rename security_pirq_sid to security_irq_sid [PATCH 7/8] xsm: clean up initial SIDs [PATCH 8/8] flask: Add flask-label-pci tool
Daniel De Graaf
2011-Nov-30 23:34 UTC
[PATCH 1/8] flask: Fix policy build with new checkpolicy
Version 26 of checkpolicy (shipped with Fedora 16) now requires that roles be declared prior to setting types for a role. Add a declaration of the system_r role to fix the build of default XSM/FLASK policy. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.te | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 0977939..d95a7da 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -151,4 +151,5 @@ sid iomem gen_context(system_u:object_r:iomem_t,s0) sid ioport gen_context(system_u:object_r:ioport_t,s0) sid device gen_context(system_u:object_r:device_t,s0) +role system_r; role system_r types { xen_type domain_type }; -- 1.7.7.3
Daniel De Graaf
2011-Nov-30 23:34 UTC
[PATCH 2/8] xsm: remove unused xsm_assign_vector check
The PHYSDEVOP_alloc_irq_vector hypercall is a noop, so its XSM check is not useful. Remove it and the "event vector" FLASK permission. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/access_vectors | 1 - tools/flask/policy/policy/modules/xen/xen.if | 1 - tools/flask/policy/policy/modules/xen/xen.te | 1 - xen/arch/x86/physdev.c | 4 ---- xen/include/xsm/xsm.h | 6 ------ xen/xsm/dummy.c | 6 ------ xen/xsm/flask/hooks.c | 13 ------------- xen/xsm/flask/include/av_perm_to_string.h | 3 +-- xen/xsm/flask/include/av_permissions.h | 3 +-- 9 files changed, 2 insertions(+), 36 deletions(-) diff --git a/tools/flask/policy/policy/flask/access_vectors b/tools/flask/policy/policy/flask/access_vectors index 9d09c5b..1b2687a 100644 --- a/tools/flask/policy/policy/flask/access_vectors +++ b/tools/flask/policy/policy/flask/access_vectors @@ -100,7 +100,6 @@ class event status notify create - vector reset } diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index bf3b794..d12af74 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -67,7 +67,6 @@ define(`create_channel'', ` ############################################################################### define(`create_passthrough_resource'', ` type $3, resource_type; - allow $1 $3:event vector; allow $1 $2:resource {add remove}; allow $1 ioport_t:resource {add_ioport use}; allow $1 iomem_t:resource {add_iomem use}; diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index d95a7da..8113467 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -31,7 +31,6 @@ 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 pirq_t:event {vector}; allow dom0_t xen_t:mmu {memorymap}; allow dom0_t dom0_t:mmu {pinpage map_read map_write adjust updatemp}; diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index cca56bb..5c7ab68 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -452,10 +452,6 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) if ( !IS_PRIV(v->domain) ) break; - ret = xsm_assign_vector(v->domain, irq_op.irq); - if ( ret ) - break; - /* Vector is only used by hypervisor, and dom0 shouldn''t touch it in its world, return irq_op.irq as the vecotr, and make this hypercall dummy, and also defer the vector diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 1f70e87..82f510d 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -129,7 +129,6 @@ struct xsm_operations { int (*hvm_set_pci_link_route) (struct domain *d); int (*hvm_inject_msi) (struct domain *d); int (*apic) (struct domain *d, int cmd); - int (*assign_vector) (struct domain *d, uint32_t pirq); int (*xen_settime) (void); int (*memtype) (uint32_t access); int (*microcode) (void); @@ -535,11 +534,6 @@ static inline int xsm_apic (struct domain *d, int cmd) return xsm_call(apic(d, cmd)); } -static inline int xsm_assign_vector (struct domain *d, uint32_t pirq) -{ - return xsm_call(assign_vector(d, pirq)); -} - static inline int xsm_xen_settime (void) { return xsm_call(xen_settime()); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 6536948..1b50d0e 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -345,11 +345,6 @@ static int dummy_apic (struct domain *d, int cmd) return 0; } -static int dummy_assign_vector (struct domain *d, uint32_t pirq) -{ - return 0; -} - static int dummy_xen_settime (void) { return 0; @@ -560,7 +555,6 @@ void xsm_fixup_ops (struct xsm_operations *ops) 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, apic); - set_to_dummy_if_null(ops, assign_vector); set_to_dummy_if_null(ops, xen_settime); set_to_dummy_if_null(ops, memtype); set_to_dummy_if_null(ops, microcode); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 37b297e..97ae4d9 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -907,18 +907,6 @@ static int flask_apic(struct domain *d, int cmd) return domain_has_xen(d, perm); } -static int flask_assign_vector(struct domain *d, uint32_t pirq) -{ - u32 psid; - struct domain_security_struct *dsec; - dsec = d->ssid; - - if ( security_pirq_sid(pirq, &psid) ) - return -EPERM; - - return avc_has_perm(dsec->sid, psid, SECCLASS_EVENT, EVENT__VECTOR, NULL); -} - static int flask_xen_settime(void) { return domain_has_xen(current->domain, XEN__SETTIME); @@ -1306,7 +1294,6 @@ static struct xsm_operations flask_ops = { .hvm_set_isa_irq_level = flask_hvm_set_isa_irq_level, .hvm_set_pci_link_route = flask_hvm_set_pci_link_route, .apic = flask_apic, - .assign_vector = flask_assign_vector, .xen_settime = flask_xen_settime, .memtype = flask_memtype, .microcode = flask_microcode, diff --git a/xen/xsm/flask/include/av_perm_to_string.h b/xen/xsm/flask/include/av_perm_to_string.h index c32488e..70aa02d 100644 --- a/xen/xsm/flask/include/av_perm_to_string.h +++ b/xen/xsm/flask/include/av_perm_to_string.h @@ -56,18 +56,17 @@ S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc") S_(SECCLASS_HVM, HVM__SETPARAM, "setparam") S_(SECCLASS_HVM, HVM__GETPARAM, "getparam") - S_(SECCLASS_HVM, HVM__TRACKDIRTYVRAM, "trackdirtyvram") S_(SECCLASS_HVM, HVM__PCILEVEL, "pcilevel") S_(SECCLASS_HVM, HVM__IRQLEVEL, "irqlevel") S_(SECCLASS_HVM, HVM__PCIROUTE, "pciroute") S_(SECCLASS_HVM, HVM__BIND_IRQ, "bind_irq") S_(SECCLASS_HVM, HVM__CACHEATTR, "cacheattr") + S_(SECCLASS_HVM, HVM__TRACKDIRTYVRAM, "trackdirtyvram") S_(SECCLASS_EVENT, EVENT__BIND, "bind") S_(SECCLASS_EVENT, EVENT__SEND, "send") S_(SECCLASS_EVENT, EVENT__STATUS, "status") S_(SECCLASS_EVENT, EVENT__NOTIFY, "notify") S_(SECCLASS_EVENT, EVENT__CREATE, "create") - S_(SECCLASS_EVENT, EVENT__VECTOR, "vector") S_(SECCLASS_EVENT, EVENT__RESET, "reset") S_(SECCLASS_GRANT, GRANT__MAP_READ, "map_read") S_(SECCLASS_GRANT, GRANT__MAP_WRITE, "map_write") diff --git a/xen/xsm/flask/include/av_permissions.h b/xen/xsm/flask/include/av_permissions.h index f5dcc6f..4c2ffb6 100644 --- a/xen/xsm/flask/include/av_permissions.h +++ b/xen/xsm/flask/include/av_permissions.h @@ -70,8 +70,7 @@ #define EVENT__STATUS 0x00000004UL #define EVENT__NOTIFY 0x00000008UL #define EVENT__CREATE 0x00000010UL -#define EVENT__VECTOR 0x00000020UL -#define EVENT__RESET 0x00000040UL +#define EVENT__RESET 0x00000020UL #define GRANT__MAP_READ 0x00000001UL #define GRANT__MAP_WRITE 0x00000002UL -- 1.7.7.3
Daniel De Graaf
2011-Nov-30 23:34 UTC
[PATCH 3/8] xsm: Revert "Fix xsm_mmu_* and xsm_update_va_mapping hooks"
This reverts 23220:56a3b9c7367f, which removes all validation of the target pages in the mapping. This crash was solved by properly marking pages without known SIDs in 22207:20f139010445. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/mm.c | 30 +++++++++++------------------- xen/include/xsm/xsm.h | 28 +++++++++++++--------------- xen/xsm/dummy.c | 11 +++++------ xen/xsm/flask/hooks.c | 41 +++++++++++++++++++++++++++++++++-------- 4 files changed, 62 insertions(+), 48 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index b00c277..64af6ff 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3517,6 +3517,9 @@ int do_mmu_update( { p2m_type_t p2mt; + rc = xsm_mmu_normal_update(d, pg_owner, req.val); + if ( rc ) + break; rc = -EINVAL; req.ptr -= cmd; @@ -3545,14 +3548,6 @@ int do_mmu_update( (unsigned long)(req.ptr & ~PAGE_MASK)); page = mfn_to_page(mfn); - rc = xsm_mmu_normal_update(d, req.val, page); - if ( rc ) { - unmap_domain_page_with_cache(va, &mapcache); - put_page(page); - put_gfn(pt_owner, gmfn); - break; - } - if ( page_lock(page) ) { switch ( page->u.inuse.type_info & PGT_type_mask ) @@ -3736,6 +3731,10 @@ int do_mmu_update( mfn = req.ptr >> PAGE_SHIFT; gpfn = req.val; + rc = xsm_mmu_machphys_update(d, mfn); + if ( rc ) + break; + if ( unlikely(!get_page_from_pagenr(mfn, pg_owner)) ) { MEM_LOG("Could not get page for mach->phys update"); @@ -3750,10 +3749,6 @@ int do_mmu_update( break; } - rc = xsm_mmu_machphys_update(d, mfn_to_page(mfn)); - if ( rc ) - break; - set_gpfn_from_mfn(mfn, gpfn); paging_mark_dirty(pg_owner, mfn); @@ -4380,6 +4375,10 @@ static int __do_update_va_mapping( perfc_incr(calls_to_update_va); + rc = xsm_update_va_mapping(d, pg_owner, val); + if ( rc ) + return rc; + rc = -EINVAL; pl1e = guest_map_l1e(v, va, &gl1mfn); if ( unlikely(!pl1e || !get_page_from_pagenr(gl1mfn, d)) ) @@ -4399,13 +4398,6 @@ static int __do_update_va_mapping( goto out; } - rc = xsm_update_va_mapping(d, val, gl1pg); - if ( rc ) { - page_unlock(gl1pg); - put_page(gl1pg); - goto out; - } - rc = mod_l1_entry(pl1e, val, gl1mfn, 0, v, pg_owner); page_unlock(gl1pg); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 82f510d..da1f5d0 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -141,12 +141,11 @@ 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, - intpte_t fpte, struct page_info *page); - int (*mmu_machphys_update) (struct domain *d, struct page_info *page); - int (*update_va_mapping) (struct domain *d, - l1_pgentry_t pte, - struct page_info *page); + int (*mmu_normal_update) (struct domain *d, 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); 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); @@ -594,22 +593,21 @@ 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, - intpte_t fpte, struct page_info *page) +static inline int xsm_mmu_normal_update (struct domain *d, struct domain *f, + intpte_t fpte) { - return xsm_call(mmu_normal_update(d, fpte, page)); + return xsm_call(mmu_normal_update(d, f, fpte)); } -static inline int xsm_mmu_machphys_update (struct domain *d, struct page_info *page) +static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn) { - return xsm_call(mmu_machphys_update(d, page)); + return xsm_call(mmu_machphys_update(d, mfn)); } -static inline int xsm_update_va_mapping(struct domain *d, - l1_pgentry_t pte, - struct page_info *page) +static inline int xsm_update_va_mapping(struct domain *d, struct domain *f, + l1_pgentry_t pte) { - return xsm_call(update_va_mapping(d, pte, page)); + return xsm_call(update_va_mapping(d, f, pte)); } static inline int xsm_add_to_physmap(struct domain *d1, struct domain *d2) diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 1b50d0e..ef461e6 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -400,20 +400,19 @@ static int dummy_domain_memory_map (struct domain *d) return 0; } -static int dummy_mmu_normal_update (struct domain *d, - intpte_t fpte, struct page_info *page) +static int dummy_mmu_normal_update (struct domain *d, struct domain *f, + intpte_t fpte) { return 0; } -static int dummy_mmu_machphys_update (struct domain *d, struct page_info *page) +static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn) { return 0; } -static int dummy_update_va_mapping (struct domain *d, - l1_pgentry_t pte, - struct page_info *page) +static int dummy_update_va_mapping (struct domain *d, struct domain *f, + l1_pgentry_t pte) { return 0; } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 97ae4d9..2cb3e16 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -348,6 +348,26 @@ static int get_page_sid(struct page_info *page, u32 *sid) return rc; } +static int get_mfn_sid(unsigned long mfn, u32 *sid) +{ + int rc = 0; + struct page_info *page; + + if ( mfn_valid(mfn) ) + { + /*mfn is valid if this is a page that Xen is tracking!*/ + page = mfn_to_page(mfn); + rc = get_page_sid(page, sid); + } + else + { + /*Possibly an untracked IO page?*/ + rc = security_iomem_sid(mfn, sid); + } + + return rc; +} + static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2) { return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__ADJUST); @@ -987,11 +1007,12 @@ 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, - intpte_t fpte, struct page_info *page) +static int flask_mmu_normal_update(struct domain *d, struct domain *f, + intpte_t fpte) { int rc = 0; u32 map_perms = MMU__MAP_READ; + unsigned long fmfn; struct domain_security_struct *dsec; u32 fsid; @@ -1000,38 +1021,42 @@ static int flask_mmu_normal_update(struct domain *d, if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW ) map_perms |= MMU__MAP_WRITE; - rc = get_page_sid(page, &fsid); + fmfn = get_gfn_untyped(f, l1e_get_pfn(l1e_from_intpte(fpte))); + + rc = get_mfn_sid(fmfn, &fsid); if ( rc ) return rc; return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, NULL); } -static int flask_mmu_machphys_update(struct domain *d, struct page_info *page) +static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) { int rc = 0; u32 psid; struct domain_security_struct *dsec; dsec = d->ssid; - rc = get_page_sid(page, &psid); + rc = get_mfn_sid(mfn, &psid); if ( rc ) return rc; return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL); } -static int flask_update_va_mapping(struct domain *d, - l1_pgentry_t pte, struct page_info *page) +static int flask_update_va_mapping(struct domain *d, struct domain *f, + l1_pgentry_t pte) { int rc = 0; u32 psid; u32 map_perms = MMU__MAP_READ; + unsigned long mfn; struct domain_security_struct *dsec; dsec = d->ssid; - rc = get_page_sid(page, &psid); + mfn = get_gfn_untyped(f, l1e_get_pfn(pte)); + rc = get_mfn_sid(mfn, &psid); if ( rc ) return rc; -- 1.7.7.3
Daniel De Graaf
2011-Nov-30 23:34 UTC
[PATCH 4/8] xsm: always allow setting non-present PTEs
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/hooks.c | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 2cb3e16..80c1f70 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -1016,6 +1016,9 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *f, struct domain_security_struct *dsec; u32 fsid; + if ( !(l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_PRESENT) ) + return 0; + dsec = d->ssid; if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW ) @@ -1053,6 +1056,12 @@ static int flask_update_va_mapping(struct domain *d, struct domain *f, unsigned long mfn; struct domain_security_struct *dsec; + if ( !(l1e_get_flags(pte) & _PAGE_PRESENT) ) + return 0; + + if ( l1e_get_flags(pte) & _PAGE_RW ) + map_perms |= MMU__MAP_WRITE; + dsec = d->ssid; mfn = get_gfn_untyped(f, l1e_get_pfn(pte)); @@ -1060,9 +1069,6 @@ static int flask_update_va_mapping(struct domain *d, struct domain *f, if ( rc ) return rc; - if ( l1e_get_flags(pte) & _PAGE_RW ) - map_perms |= MMU__MAP_WRITE; - return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, map_perms, NULL); } -- 1.7.7.3
The XSM hooks inside rangeset are not useful in capturing the PIRQ mappings in HVM domains. They can also be called from softirq context where current->domain is invalid, causing spurious AVC denials from unrelated domains on such calls. Within FLASK code, the rangeset hooks were already divided between IRQs, I/O memory, and x86 IO ports; propagate this division back through the XSM hooks and call the XSM functions directly when needed. This removes XSM checks for the initial rangeset population for dom0 and the removal checks on domain destruction; denying either of these actions does not make sense. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/domctl.c | 24 +++++++++++++-- xen/arch/x86/irq.c | 9 ++++++ xen/arch/x86/physdev.c | 4 ++ xen/common/domctl.c | 10 +++++- xen/common/rangeset.c | 8 ----- xen/include/xsm/xsm.h | 22 ++++++++------ xen/xsm/dummy.c | 14 ++++++--- xen/xsm/flask/hooks.c | 73 ++++++++++++------------------------------------ 8 files changed, 81 insertions(+), 83 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 5ed211f..a676f79 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -76,6 +76,7 @@ long arch_do_domctl( struct domain *d; unsigned int fp = domctl->u.ioport_permission.first_port; unsigned int np = domctl->u.ioport_permission.nr_ports; + int allow = domctl->u.ioport_permission.allow_access; ret = -EINVAL; if ( (fp + np) > 65536 ) @@ -87,7 +88,9 @@ long arch_do_domctl( if ( np == 0 ) ret = 0; - else if ( domctl->u.ioport_permission.allow_access ) + else if ( xsm_ioport_permission(d, fp, fp + np - 1, allow) ) + ret = -EPERM; + else if ( allow ) ret = ioports_permit_access(d, fp, fp + np - 1); else ret = ioports_deny_access(d, fp, fp + np - 1); @@ -822,6 +825,7 @@ long arch_do_domctl( unsigned long gfn = domctl->u.memory_mapping.first_gfn; unsigned long mfn = domctl->u.memory_mapping.first_mfn; unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns; + int add = domctl->u.memory_mapping.add_mapping; int i; ret = -EINVAL; @@ -837,8 +841,13 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) break; - ret=0; - if ( domctl->u.memory_mapping.add_mapping ) + ret = xsm_iomem_permission(d, mfn, mfn + nr_mfns - 1, add); + if ( ret ) { + rcu_unlock_domain(d); + break; + } + + if ( add ) { gdprintk(XENLOG_INFO, "memory_map:add: gfn=%lx mfn=%lx nr_mfns=%lx\n", @@ -871,6 +880,7 @@ long arch_do_domctl( unsigned int fgp = domctl->u.ioport_mapping.first_gport; unsigned int fmp = domctl->u.ioport_mapping.first_mport; unsigned int np = domctl->u.ioport_mapping.nr_ports; + unsigned int add = domctl->u.ioport_mapping.add_mapping; struct g2m_ioport *g2m_ioport; int found = 0; @@ -893,8 +903,14 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) ) break; + ret = xsm_ioport_permission(d, fmp, fmp + np - 1, add); + if ( ret ) { + rcu_unlock_domain(d); + break; + } + hd = domain_hvm_iommu(d); - if ( domctl->u.ioport_mapping.add_mapping ) + if ( add ) { gdprintk(XENLOG_INFO, "ioport_map:add f_gport=%x f_mport=%x np=%x\n", diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 9149096..b1c5d42 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -18,6 +18,7 @@ #include <xen/iocap.h> #include <xen/iommu.h> #include <xen/trace.h> +#include <xsm/xsm.h> #include <asm/msi.h> #include <asm/current.h> #include <asm/flushtlb.h> @@ -1817,6 +1818,14 @@ int map_domain_pirq( return 0; } + ret = xsm_irq_permission(d, irq, 1); + if ( ret ) + { + dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n", + d->domain_id, irq, pirq); + return ret; + } + ret = irq_permit_access(d, pirq); if ( ret ) { diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 5c7ab68..5a4acae 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -229,6 +229,10 @@ int physdev_unmap_pirq(domid_t domid, int pirq) if ( !IS_PRIV_FOR(current->domain, d) ) goto free_domain; + ret = xsm_irq_permission(d, pirq, 0); + if ( ret ) + goto free_domain; + spin_lock(&pcidevs_lock); spin_lock(&d->event_lock); ret = unmap_domain_pirq(d, pirq); diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 6705a57..06594a0 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -858,6 +858,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) { struct domain *d; unsigned int pirq = op->u.irq_permission.pirq; + int allow = op->u.irq_permission.allow_access; ret = -ESRCH; d = rcu_lock_domain_by_id(op->domain); @@ -866,7 +867,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( pirq >= d->nr_pirqs ) ret = -EINVAL; - else if ( op->u.irq_permission.allow_access ) + else if ( xsm_irq_permission(d, pirq, allow) ) + ret = -EPERM; + else if ( allow ) ret = irq_permit_access(d, pirq); else ret = irq_deny_access(d, pirq); @@ -880,6 +883,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) struct domain *d; unsigned long mfn = op->u.iomem_permission.first_mfn; unsigned long nr_mfns = op->u.iomem_permission.nr_mfns; + int allow = op->u.iomem_permission.allow_access; ret = -EINVAL; if ( (mfn + nr_mfns - 1) < mfn ) /* wrap? */ @@ -890,7 +894,9 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) if ( d == NULL ) break; - if ( op->u.iomem_permission.allow_access ) + if ( xsm_iomem_permission(d, mfn, mfn + nr_mfns - 1, allow) ) + ret = -EPERM; + else if ( allow ) ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); else ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c index bb9523f..f09c0c4 100644 --- a/xen/common/rangeset.c +++ b/xen/common/rangeset.c @@ -97,10 +97,6 @@ int rangeset_add_range( struct range *x, *y; int rc = 0; - rc = xsm_add_range(r->domain, r->name, s, e); - if ( rc ) - return rc; - ASSERT(s <= e); spin_lock(&r->lock); @@ -169,10 +165,6 @@ int rangeset_remove_range( struct range *x, *y, *t; int rc = 0; - rc = xsm_remove_range(r->domain, r->name, s, e); - if ( rc ) - return rc; - ASSERT(s <= e); spin_lock(&r->lock); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index da1f5d0..45fee21 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -106,8 +106,8 @@ struct xsm_operations { int (*kexec) (void); int (*schedop_shutdown) (struct domain *d1, struct domain *d2); - int (*add_range) (struct domain *d, char *name, unsigned long s, unsigned long e); - int (*remove_range) (struct domain *d, char *name, unsigned long s, unsigned long e); + int (*irq_permission) (struct domain *d, int pirq, uint8_t allow); + int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow); int (*test_assign_device) (uint32_t machine_bdf); int (*assign_device) (struct domain *d, uint32_t machine_bdf); @@ -152,6 +152,7 @@ struct xsm_operations { int (*pin_mem_cacheattr) (struct domain *d); int (*ext_vcpucontext) (struct domain *d, uint32_t cmd); int (*vcpuextstate) (struct domain *d, uint32_t cmd); + int (*ioport_permission) (struct domain *d, uint32_t s, uint32_t e, uint8_t allow); #endif }; @@ -415,16 +416,14 @@ static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2) return xsm_call(schedop_shutdown(d1, d2)); } -static inline int xsm_add_range (struct domain *d, char *name, unsigned long s, - unsigned long e) +static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow) { - return xsm_call(add_range(d, name, s, e)); + return xsm_call(irq_permission(d, pirq, allow)); } - -static inline int xsm_remove_range (struct domain *d, char *name, unsigned long s, - unsigned long e) + +static inline int xsm_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { - return xsm_call(remove_range(d, name, s, e)); + return xsm_call(iomem_permission(d, s, e, allow)); } static inline int xsm_test_assign_device(uint32_t machine_bdf) @@ -639,6 +638,11 @@ static inline int xsm_vcpuextstate(struct domain *d, uint32_t cmd) { return xsm_call(vcpuextstate(d, cmd)); } + +static inline int xsm_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + return xsm_call(ioport_permission(d, s, e, allow)); +} #endif /* CONFIG_X86 */ extern struct xsm_operations dummy_xsm_ops; diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index ef461e6..a629396 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -273,13 +273,12 @@ static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op) return -ENOSYS; } -static int dummy_add_range (struct domain *d, char *name, unsigned long s, unsigned long e) +static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow) { return 0; } -static int dummy_remove_range (struct domain *d, char *name, unsigned long s, - unsigned long e) +static int dummy_iomem_permission (struct domain *d, uint64_t s, uint64_t e, uint8_t allow) { return 0; } @@ -462,6 +461,10 @@ static int dummy_vcpuextstate (struct domain *d, uint32_t cmd) return 0; } +static int dummy_ioport_permission (struct domain *d, uint32_t s, uint32_t e, uint8_t allow) +{ + return 0; +} #endif struct xsm_operations dummy_xsm_ops; @@ -536,8 +539,8 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, kexec); set_to_dummy_if_null(ops, schedop_shutdown); - set_to_dummy_if_null(ops, add_range); - set_to_dummy_if_null(ops, remove_range); + set_to_dummy_if_null(ops, irq_permission); + set_to_dummy_if_null(ops, iomem_permission); set_to_dummy_if_null(ops, __do_xsm_op); @@ -577,5 +580,6 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, pin_mem_cacheattr); set_to_dummy_if_null(ops, ext_vcpucontext); set_to_dummy_if_null(ops, vcpuextstate); + set_to_dummy_if_null(ops, ioport_permission); #endif } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 80c1f70..1bea498 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -643,7 +643,7 @@ static inline u32 resource_to_perm(uint8_t access) return RESOURCE__REMOVE; } -static int irq_has_perm(struct domain *d, uint8_t pirq, uint8_t access) +static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) { u32 perm; u32 rsid; @@ -678,10 +678,9 @@ static int irq_has_perm(struct domain *d, uint8_t pirq, uint8_t access) return rc; if ( access ) - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, + rc = avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); - else - return rc; + return rc; } struct iomem_has_perm_data { @@ -706,7 +705,7 @@ static int _iomem_has_perm(void *v, u32 sid, unsigned long start, unsigned long return avc_has_perm(data->tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } -static int iomem_has_perm(struct domain *d, unsigned long start, unsigned long end, uint8_t access) +static int flask_iomem_permission(struct domain *d, uint64_t start, uint64_t end, uint8_t access) { struct iomem_has_perm_data data; int rc; @@ -784,7 +783,7 @@ static int _ioport_has_perm(void *v, u32 sid, unsigned long start, unsigned long } -static int ioport_has_perm(struct domain *d, uint32_t start, uint32_t end, uint8_t access) +static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t end, uint8_t access) { int rc; struct ioport_has_perm_data data; @@ -1142,23 +1141,30 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b { u32 rsid; int rc = -EPERM; + int irq; struct domain_security_struct *ssec, *tsec; + struct avc_audit_data ad; rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); if ( rc ) return rc; - rc = security_pirq_sid(bind->machine_irq, &rsid); + irq = domain_pirq_to_irq(d, bind->machine_irq); + + rc = security_pirq_sid(irq, &rsid); if ( rc ) return rc; + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = (unsigned long)irq; + ssec = current->domain->ssid; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, NULL); + rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad); if ( rc ) return rc; tsec = d->ssid; - return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, NULL); + return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); } static int flask_pin_mem_cacheattr (struct domain *d) @@ -1205,50 +1211,6 @@ static int flask_vcpuextstate (struct domain *d, uint32_t cmd) } #endif -static int io_has_perm(struct domain *d, char *name, unsigned long s, - unsigned long e, u32 access) -{ - int rc = -EPERM; - - if ( strcmp(name, "I/O Memory") == 0 ) - { - rc = iomem_has_perm(d, s, e, access); - if ( rc ) - return rc; - } - else if ( strcmp(name, "Interrupts") == 0 ) - { - while (s <= e) { - rc = irq_has_perm(d, s, access); - if ( rc ) - return rc; - s++; - } - } -#ifdef CONFIG_X86 - else if ( strcmp(name, "I/O Ports") == 0 ) - { - rc = ioport_has_perm(d, s, e, access); - if ( rc ) - return rc; - } -#endif - - return rc; -} - -static int flask_add_range(struct domain *d, char *name, unsigned long s, - unsigned long e) -{ - return io_has_perm(d, name, s, e, 1); -} - -static int flask_remove_range(struct domain *d, char *name, unsigned long s, - unsigned long e) -{ - return io_has_perm(d, name, s, e, 0); -} - long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op); static struct xsm_operations flask_ops = { @@ -1308,8 +1270,8 @@ static struct xsm_operations flask_ops = { .kexec = flask_kexec, .schedop_shutdown = flask_schedop_shutdown, - .add_range = flask_add_range, - .remove_range = flask_remove_range, + .irq_permission = flask_irq_permission, + .iomem_permission = flask_iomem_permission, .__do_xsm_op = do_flask_op, @@ -1348,6 +1310,7 @@ static struct xsm_operations flask_ops = { .pin_mem_cacheattr = flask_pin_mem_cacheattr, .ext_vcpucontext = flask_ext_vcpucontext, .vcpuextstate = flask_vcpuextstate, + .ioport_permission = flask_ioport_permission, #endif }; -- 1.7.7.3
Daniel De Graaf
2011-Nov-30 23:34 UTC
[PATCH 6/8] xsm: rename security_pirq_sid to security_irq_sid
Attempting to manage the PIRQ namespace is not useful as guests can assign any mapping of IRQ to PIRQ (although the identity mapping is the most common). Change the internal names to reflect this change. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/hooks.c | 4 ++-- xen/xsm/flask/include/security.h | 2 +- xen/xsm/flask/ss/services.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 1bea498..0feb070 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -666,7 +666,7 @@ static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) ssec = current->domain->ssid; tsec = d->ssid; - rc = security_pirq_sid(pirq, &rsid); + rc = security_irq_sid(pirq, &rsid); if ( rc ) return rc; @@ -1151,7 +1151,7 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b irq = domain_pirq_to_irq(d, bind->machine_irq); - rc = security_pirq_sid(irq, &rsid); + rc = security_irq_sid(irq, &rsid); if ( rc ) return rc; diff --git a/xen/xsm/flask/include/security.h b/xen/xsm/flask/include/security.h index 0dc21c8..67ca6d0 100644 --- a/xen/xsm/flask/include/security.h +++ b/xen/xsm/flask/include/security.h @@ -71,7 +71,7 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *out_sid); int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel); -int security_pirq_sid(int pirq, u32 *out_sid); +int security_irq_sid(int pirq, u32 *out_sid); int security_iomem_sid(unsigned long, u32 *out_sid); diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index b880762..1eb8e4c 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1514,11 +1514,11 @@ err: } /** - * security_pirq_sid - Obtain the SID for a physical irq. + * security_irq_sid - Obtain the SID for a physical irq. * @pirq: physical irq * @out_sid: security identifier */ -int security_pirq_sid(int pirq, u32 *out_sid) +int security_irq_sid(int pirq, u32 *out_sid) { int rc = 0; struct ocontext *c; -- 1.7.7.3
The domU SID is never used before a policy load, and so does not belong in the initial_sids list. The PIRQ SID is now incorrectly named; it should simply be called IRQ. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/flask/initial_sids | 3 +-- tools/flask/policy/policy/modules/xen/xen.if | 4 ++-- tools/flask/policy/policy/modules/xen/xen.te | 9 ++++----- xen/xsm/flask/include/flask.h | 19 +++++++++---------- xen/xsm/flask/include/initial_sid_to_string.h | 3 +-- xen/xsm/flask/ss/services.c | 2 +- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/tools/flask/policy/policy/flask/initial_sids b/tools/flask/policy/policy/flask/initial_sids index 9b78fba..e508bde 100644 --- a/tools/flask/policy/policy/flask/initial_sids +++ b/tools/flask/policy/policy/flask/initial_sids @@ -5,13 +5,12 @@ # sid xen sid dom0 -sid domU sid domio sid domxen sid unlabeled sid security sid ioport sid iomem -sid pirq +sid irq sid device # FLASK diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index d12af74..1b50898 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -70,10 +70,10 @@ define(`create_passthrough_resource'', ` allow $1 $2:resource {add remove}; allow $1 ioport_t:resource {add_ioport use}; allow $1 iomem_t:resource {add_iomem use}; - allow $1 pirq_t:resource {add_irq 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 pirq_t:resource {use}; + 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}; diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 8113467..1a7f29a 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -16,7 +16,7 @@ type unlabeled_t, domain_type; type security_t, domain_type; -type pirq_t, resource_type; +type irq_t, resource_type; type ioport_t, resource_type; type iomem_t, resource_type; type device_t, resource_type; @@ -43,8 +43,8 @@ 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 pirq_t:resource {add_irq remove_irq}; -allow dom0_t pirq_t:resource { add_irq remove_irq use}; +allow xen_t irq_t:resource {add_irq remove_irq}; +allow dom0_t irq_t:resource { add_irq remove_irq use}; allow dom0_t dom0_t:resource { add remove }; allow dom0_t xen_t:xen firmware; @@ -140,12 +140,11 @@ manage_domain(dom0_t, domHU_t) ################################################################################ sid xen gen_context(system_u:system_r:xen_t,s0) sid dom0 gen_context(system_u:system_r:dom0_t,s0) -sid domU gen_context(system_u:system_r:domU_t,s0) sid domxen gen_context(system_u:system_r:domxen_t,s0) sid domio gen_context(system_u:system_r:domio_t,s0) sid unlabeled gen_context(system_u:system_r:unlabeled_t,s0) sid security gen_context(system_u:system_r:security_t,s0) -sid pirq gen_context(system_u:object_r:pirq_t,s0) +sid irq gen_context(system_u:object_r:irq_t,s0) sid iomem gen_context(system_u:object_r:iomem_t,s0) sid ioport gen_context(system_u:object_r:ioport_t,s0) sid device gen_context(system_u:object_r:device_t,s0) diff --git a/xen/xsm/flask/include/flask.h b/xen/xsm/flask/include/flask.h index 333edcd..6d29c5a 100644 --- a/xen/xsm/flask/include/flask.h +++ b/xen/xsm/flask/include/flask.h @@ -20,16 +20,15 @@ */ #define SECINITSID_XEN 1 #define SECINITSID_DOM0 2 -#define SECINITSID_DOMU 3 -#define SECINITSID_DOMIO 4 -#define SECINITSID_DOMXEN 5 -#define SECINITSID_UNLABELED 6 -#define SECINITSID_SECURITY 7 -#define SECINITSID_IOPORT 8 -#define SECINITSID_IOMEM 9 -#define SECINITSID_PIRQ 10 -#define SECINITSID_DEVICE 11 +#define SECINITSID_DOMIO 3 +#define SECINITSID_DOMXEN 4 +#define SECINITSID_UNLABELED 5 +#define SECINITSID_SECURITY 6 +#define SECINITSID_IOPORT 7 +#define SECINITSID_IOMEM 8 +#define SECINITSID_IRQ 9 +#define SECINITSID_DEVICE 10 -#define SECINITSID_NUM 11 +#define SECINITSID_NUM 10 #endif diff --git a/xen/xsm/flask/include/initial_sid_to_string.h b/xen/xsm/flask/include/initial_sid_to_string.h index 3bf8ff2..814f4bf 100644 --- a/xen/xsm/flask/include/initial_sid_to_string.h +++ b/xen/xsm/flask/include/initial_sid_to_string.h @@ -4,14 +4,13 @@ static char *initial_sid_to_string[] "null", "xen", "dom0", - "domU", "domio", "domxen", "unlabeled", "security", "ioport", "iomem", - "pirq", + "irq", "device", }; diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index 1eb8e4c..c810e9b 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1546,7 +1546,7 @@ int security_irq_sid(int pirq, u32 *out_sid) } else { - *out_sid = SECINITSID_PIRQ; + *out_sid = SECINITSID_IRQ; } out: -- 1.7.7.3
This allows a PCI device and its associated resources to be labeled without hardcoding addresses (which may change from system to system) in the security policy. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/utils/Makefile | 5 +- tools/flask/utils/label-pci.c | 123 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+), 1 deletions(-) create mode 100644 tools/flask/utils/label-pci.c diff --git a/tools/flask/utils/Makefile b/tools/flask/utils/Makefile index 25729a1..171a728 100644 --- a/tools/flask/utils/Makefile +++ b/tools/flask/utils/Makefile @@ -11,7 +11,7 @@ TESTDIR = testsuite/tmp TESTFLAGS= -DTESTING TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR) -CLIENTS := flask-loadpolicy flask-setenforce flask-getenforce +CLIENTS := flask-loadpolicy flask-setenforce flask-getenforce flask-label-pci CLIENTS_SRCS := $(patsubst flask-%,%.c,$(CLIENTS)) CLIENTS_OBJS := $(patsubst flask-%,%.o,$(CLIENTS)) @@ -27,6 +27,9 @@ flask-setenforce: setenforce.o flask-getenforce: getenforce.o $(CC) $(LDFLAGS) $< $(LDLIBS) -L$(LIBFLASK_ROOT) -lflask $(LDLIBS_libxenctrl) -o $@ +flask-label-pci: label-pci.o + $(CC) $(LDFLAGS) $< $(LDLIBS) -L$(LIBFLASK_ROOT) -lflask $(LDLIBS_libxenctrl) -o $@ + .PHONY: clean clean: rm -f *.o *.opic *.so diff --git a/tools/flask/utils/label-pci.c b/tools/flask/utils/label-pci.c new file mode 100644 index 0000000..839ad61 --- /dev/null +++ b/tools/flask/utils/label-pci.c @@ -0,0 +1,123 @@ +/* + * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <xenctrl.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <string.h> +#include <unistd.h> +#include <libflask.h> + +/* Pulled from linux/include/linux/ioport.h */ +#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */ +#define IORESOURCE_IO 0x00000100 +#define IORESOURCE_MEM 0x00000200 +#define IORESOURCE_IRQ 0x00000400 +#define IORESOURCE_DMA 0x00000800 +#define IORESOURCE_BUS 0x00001000 + + +static void usage (int argCnt, char *argv[]) +{ + fprintf(stderr, "Usage: %s SBDF label\n", argv[0]); + exit(1); +} + +int main (int argCnt, char *argv[]) +{ + int ret, err = 0; + xc_interface *xch = 0; + int seg, bus, dev, fn; + uint32_t sbdf; + uint64_t start, end, flags; + char buf[1024]; + FILE *f; + + if (argCnt != 3) + usage(argCnt, argv); + + xch = xc_interface_open(0,0,0); + if ( !xch ) + { + fprintf(stderr, "Unable to create interface to xenctrl: %s\n", + strerror(errno)); + err = 1; + goto done; + } + + sscanf(argv[1], "%x:%x:%x.%d", &seg, &bus, &dev, &fn); + sbdf = (seg << 16) | (bus << 8) | (dev << 3) | fn; + + snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%04x:%02x:%02x.%d/resource", + seg, bus, dev, fn); + + f = fopen(buf, "r"); + if (!f) { + fprintf(stderr, "Unable to find device %s: %s\n", argv[1], + strerror(errno)); + err = 1; + goto done; + } + + ret = flask_add_device(xch, sbdf, argv[2]); + if (ret) { + fprintf(stderr, "flask_add_device: Unable to set context of PCI device %s (0x%x) to %s: %d\n", + argv[1], sbdf, argv[2], ret); + err = 2; + goto done; + } + + while (fscanf(f, "0x%lx 0x%lx 0x%lx\n", &start, &end, &flags) == 3) { + if (flags & IORESOURCE_IO) { + // printf("Port %lx-%lx\n", start, end); + ret = flask_add_ioport(xch, start, end, argv[2]); + if (ret) { + fprintf(stderr, "flask_add_ioport %lx-%lx failed: %d\n", + start, end, ret); + err = 2; + } + } else if (flags & IORESOURCE_MEM) { + start >>= 12; + end >>= 12; + // printf("IOMEM %lx-%lx\n", start, end); + ret = flask_add_iomem(xch, start, end, argv[2]); + if (ret) { + fprintf(stderr, "flask_add_iomem %lx-%lx failed: %d\n", + start, end, ret); + err = 2; + } + } + } + fclose(f); + + snprintf(buf, sizeof(buf), "/sys/bus/pci/devices/%04x:%02x:%02x.%d/irq", + seg, bus, dev, fn); + f = fopen(buf, "r"); + if (!f) + goto done; + start = 0; + fscanf(f, "%ld", &start); + if (start) { + ret = flask_add_pirq(xch, start, argv[2]); + if (ret) { + fprintf(stderr, "flask_add_pirq %ld failed: %d\n", + start, ret); + err = 2; + } + } + fclose(f); +done: + if ( xch ) + xc_interface_close(xch); + + return err; +} -- 1.7.7.3