diff options
-rw-r--r-- | xen/arch/x86/domctl.c | 23 | ||||
-rw-r--r-- | xen/arch/x86/mm.c | 4 | ||||
-rw-r--r-- | xen/include/xsm/xsm.h | 23 | ||||
-rw-r--r-- | xen/xsm/dummy.c | 6 | ||||
-rw-r--r-- | xen/xsm/flask/hooks.c | 189 |
5 files changed, 80 insertions, 165 deletions
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 135ea6eca0..97a13fba99 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -114,7 +114,7 @@ long arch_do_domctl( page = mfn_to_page(mfn); - ret = xsm_getpageframeinfo(page); + ret = xsm_getpageframeinfo(d); if ( ret ) { rcu_unlock_domain(d); @@ -170,6 +170,13 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) break; + ret = xsm_getpageframeinfo(d); + if ( ret ) + { + rcu_unlock_domain(d); + break; + } + if ( unlikely(num > 1024) || unlikely(num != domctl->u.getpageframeinfo3.num) ) { @@ -209,8 +216,6 @@ long arch_do_domctl( if ( unlikely(!page) || unlikely(is_xen_heap_page(page)) ) type = XEN_DOMCTL_PFINFO_XTAB; - else if ( xsm_getpageframeinfo(page) != 0 ) - ; else { switch( page->u.inuse.type_info & PGT_type_mask ) @@ -267,6 +272,13 @@ long arch_do_domctl( if ( unlikely((d = rcu_lock_domain_by_id(dom)) == NULL) ) break; + ret = xsm_getpageframeinfo(d); + if ( ret ) + { + rcu_unlock_domain(d); + break; + } + if ( unlikely(num > 1024) ) { ret = -E2BIG; @@ -310,11 +322,6 @@ long arch_do_domctl( if ( unlikely(!page) || unlikely(is_xen_heap_page(page)) ) arr32[j] |= XEN_DOMCTL_PFINFO_XTAB; - else if ( xsm_getpageframeinfo(page) != 0 ) - { - put_page(page); - continue; - } else { unsigned long type = 0; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 84820f1d69..d02fe9703d 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3073,7 +3073,7 @@ long do_mmuext_op( break; } - if ( (rc = xsm_memory_pin_page(d, page)) != 0 ) + if ( (rc = xsm_memory_pin_page(d, pg_owner, page)) != 0 ) { put_page_and_type(page); okay = 0; @@ -3643,7 +3643,7 @@ long do_mmu_update( mfn = req.ptr >> PAGE_SHIFT; gpfn = req.val; - rc = xsm_mmu_machphys_update(d, mfn); + rc = xsm_mmu_machphys_update(d, pg_owner, mfn); if ( rc ) break; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index bef79df8cd..593cdbd10d 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -105,7 +105,7 @@ struct xsm_operations { 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); + int (*memory_pin_page) (struct domain *d1, struct domain *d2, struct page_info *page); int (*remove_from_physmap) (struct domain *d1, struct domain *d2); int (*console_io) (struct domain *d, int cmd); @@ -143,7 +143,7 @@ struct xsm_operations { #ifdef CONFIG_X86 int (*shadow_control) (struct domain *d, uint32_t op); - int (*getpageframeinfo) (struct page_info *page); + int (*getpageframeinfo) (struct domain *d); int (*getmemlist) (struct domain *d); int (*hypercall_init) (struct domain *d); int (*hvmcontext) (struct domain *d, uint32_t op); @@ -171,9 +171,8 @@ struct xsm_operations { int (*domain_memory_map) (struct domain *d); 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); + int (*mmu_machphys_update) (struct domain *d1, struct domain *d2, 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); @@ -455,9 +454,10 @@ static inline int xsm_memory_stat_reservation (struct domain *d1, return xsm_call(memory_stat_reservation(d1, d2)); } -static inline int xsm_memory_pin_page(struct domain *d, struct page_info *page) +static inline int xsm_memory_pin_page(struct domain *d1, struct domain *d2, + struct page_info *page) { - return xsm_call(memory_pin_page(d, page)); + return xsm_call(memory_pin_page(d1, d2, page)); } static inline int xsm_remove_from_physmap(struct domain *d1, struct domain *d2) @@ -617,9 +617,9 @@ static inline int xsm_shadow_control (struct domain *d, uint32_t op) return xsm_call(shadow_control(d, op)); } -static inline int xsm_getpageframeinfo (struct page_info *page) +static inline int xsm_getpageframeinfo (struct domain *d) { - return xsm_call(getpageframeinfo(page)); + return xsm_call(getpageframeinfo(d)); } static inline int xsm_getmemlist (struct domain *d) @@ -753,9 +753,10 @@ static inline int xsm_mmu_normal_update (struct domain *d, struct domain *t, return xsm_call(mmu_normal_update(d, t, f, fpte)); } -static inline int xsm_mmu_machphys_update (struct domain *d, unsigned long mfn) +static inline int xsm_mmu_machphys_update (struct domain *d1, struct domain *d2, + unsigned long mfn) { - return xsm_call(mmu_machphys_update(d, mfn)); + return xsm_call(mmu_machphys_update(d1, d2, mfn)); } static inline int xsm_update_va_mapping(struct domain *d, struct domain *f, diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 5d35342251..4836fc0f67 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -243,7 +243,7 @@ static int dummy_schedop_shutdown (struct domain *d1, struct domain *d2) return 0; } -static int dummy_memory_pin_page(struct domain *d, struct page_info *page) +static int dummy_memory_pin_page(struct domain *d1, struct domain *d2, struct page_info *page) { return 0; } @@ -418,7 +418,7 @@ static int dummy_shadow_control (struct domain *d, uint32_t op) return 0; } -static int dummy_getpageframeinfo (struct page_info *page) +static int dummy_getpageframeinfo (struct domain *d) { return 0; } @@ -554,7 +554,7 @@ static int dummy_mmu_normal_update (struct domain *d, struct domain *t, return 0; } -static int dummy_mmu_machphys_update (struct domain *d, unsigned long mfn) +static int dummy_mmu_machphys_update (struct domain *d, struct domain *f, unsigned long mfn) { return 0; } diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index de79d66b50..8c853de6bb 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -108,15 +108,21 @@ static int flask_domain_alloc_security(struct domain *d) memset(dsec, 0, sizeof(struct domain_security_struct)); - if ( is_idle_domain(d) ) + dsec->create_sid = SECSID_NULL; + switch ( d->domain_id ) { + case DOMID_IDLE: dsec->sid = SECINITSID_XEN; dsec->create_sid = SECINITSID_DOM0; - } - else - { + break; + case DOMID_XEN: + dsec->sid = SECINITSID_DOMXEN; + break; + case DOMID_IO: + dsec->sid = SECINITSID_DOMIO; + break; + default: dsec->sid = SECINITSID_UNLABELED; - dsec->create_sid = SECSID_NULL; } d->ssid = dsec; @@ -361,64 +367,6 @@ static int flask_grant_query_size(struct domain *d1, struct domain *d2) return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__QUERY); } -static int get_page_sid(struct page_info *page, u32 *sid) -{ - int rc = 0; - struct domain *d; - struct domain_security_struct *dsec; - unsigned long mfn; - - d = page_get_owner(page); - - if ( d == NULL ) - { - mfn = page_to_mfn(page); - rc = security_iomem_sid(mfn, sid); - return rc; - } - - switch ( d->domain_id ) - { - case DOMID_IO: - /*A tracked IO page?*/ - *sid = SECINITSID_DOMIO; - break; - - case DOMID_XEN: - /*A page from Xen's private heap?*/ - *sid = SECINITSID_DOMXEN; - break; - - default: - /*Pages are implicitly labeled by domain ownership!*/ - dsec = d->ssid; - *sid = dsec ? dsec->sid : SECINITSID_UNLABELED; - break; - } - - 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_get_pod_target(struct domain *d) { return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__GETPODTARGET); @@ -439,18 +387,10 @@ static int flask_memory_stat_reservation(struct domain *d1, struct domain *d2) return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__STAT); } -static int flask_memory_pin_page(struct domain *d, struct page_info *page) +static int flask_memory_pin_page(struct domain *d1, struct domain *d2, + struct page_info *page) { - int rc = 0; - u32 sid; - struct domain_security_struct *dsec; - dsec = d->ssid; - - rc = get_page_sid(page, &sid); - if ( rc ) - return rc; - - return avc_has_perm(dsec->sid, sid, SECCLASS_MMU, MMU__PINPAGE, NULL); + return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PINPAGE); } static int flask_console_io(struct domain *d, int cmd) @@ -1095,19 +1035,9 @@ static int flask_ioport_permission(struct domain *d, uint32_t start, uint32_t en return security_iterate_ioport_sids(start, end, _ioport_has_perm, &data); } -static int flask_getpageframeinfo(struct page_info *page) +static int flask_getpageframeinfo(struct domain *d) { - int rc = 0; - u32 tsid; - struct domain_security_struct *dsec; - - dsec = current->domain->ssid; - - rc = get_page_sid(page, &tsid); - if ( rc ) - return rc; - - return avc_has_perm(dsec->sid, tsid, SECCLASS_MMU, MMU__PAGEINFO, NULL); + return domain_has_perm(current->domain, d, SECCLASS_MMU, MMU__PAGEINFO); } static int flask_getmemlist(struct domain *d) @@ -1314,88 +1244,65 @@ 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 *t, - struct domain *f, intpte_t fpte) +static int domain_memory_perm(struct domain *d, struct domain *f, l1_pgentry_t pte) { int rc = 0; u32 map_perms = MMU__MAP_READ; unsigned long fgfn, fmfn; - struct domain_security_struct *dsec; - u32 fsid; - struct avc_audit_data ad; p2m_type_t p2mt; - 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) ) + if ( !(l1e_get_flags(pte) & _PAGE_PRESENT) ) return 0; - dsec = d->ssid; - - if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW ) + if ( l1e_get_flags(pte) & _PAGE_RW ) map_perms |= MMU__MAP_WRITE; - AVC_AUDIT_DATA_INIT(&ad, MEMORY); - fgfn = l1e_get_pfn(l1e_from_intpte(fpte)); + fgfn = l1e_get_pfn(pte); fmfn = mfn_x(get_gfn_query(f, fgfn, &p2mt)); - - ad.sdom = d; - ad.tdom = f; - ad.memory.pte = fpte; - ad.memory.mfn = fmfn; - - rc = get_mfn_sid(fmfn, &fsid); - put_gfn(f, fgfn); - if ( rc ) - return rc; + if ( f->domain_id == DOMID_IO || !mfn_valid(fmfn) ) + { + struct avc_audit_data ad; + struct domain_security_struct *dsec = d->ssid; + u32 fsid; + AVC_AUDIT_DATA_INIT(&ad, MEMORY); + ad.sdom = d; + ad.tdom = f; + ad.memory.pte = pte.l1; + ad.memory.mfn = fmfn; + rc = security_iomem_sid(fmfn, &fsid); + if ( rc ) + return rc; + return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, &ad); + } - return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, &ad); + return domain_has_perm(d, f, SECCLASS_MMU, map_perms); } -static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) +static int flask_mmu_normal_update(struct domain *d, struct domain *t, + struct domain *f, intpte_t fpte) { int rc = 0; - u32 psid; - struct domain_security_struct *dsec; - dsec = d->ssid; - rc = get_mfn_sid(mfn, &psid); + if (d != t) + rc = domain_has_perm(d, t, SECCLASS_MMU, MMU__REMOTE_REMAP); if ( rc ) return rc; - return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, MMU__UPDATEMP, NULL); + return domain_memory_perm(d, f, l1e_from_intpte(fpte)); +} + +static int flask_mmu_machphys_update(struct domain *d1, struct domain *d2, + unsigned long mfn) +{ + return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__UPDATEMP); } 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; - struct page_info *page = NULL; - 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; - - page = get_page_from_gfn(f, l1e_get_pfn(pte), NULL, P2M_ALLOC); - rc = get_mfn_sid(page ? page_to_mfn(page) : INVALID_MFN, &psid); - if ( page ) - put_page(page); - if ( rc ) - return rc; - - return avc_has_perm(dsec->sid, psid, SECCLASS_MMU, map_perms, NULL); + return domain_memory_perm(d, f, pte); } static int flask_add_to_physmap(struct domain *d1, struct domain *d2) |