📄 hooks.c
字号:
/* * This file contains the Flask hook function implementations for Xen. * * Author: George Coker, <gscoker@alpha.ncsc.mil> * * 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 <xen/init.h>#include <xen/lib.h>#include <xen/sched.h>#include <xen/xmalloc.h>#include <xsm/xsm.h>#include <xen/spinlock.h>#include <xen/cpumask.h>#include <xen/errno.h>#include <xen/guest_access.h>#include <public/xen.h>#include <public/physdev.h>#include <public/platform.h>#include <public/xsm/flask_op.h>#include <avc.h>#include <avc_ss.h>#include <objsec.h>#include <conditional.h>struct xsm_operations *original_ops = NULL;static int domain_has_perm(struct domain *dom1, struct domain *dom2, u16 class, u32 perms){ struct domain_security_struct *dsec1, *dsec2; dsec1 = dom1->ssid; dsec2 = dom2->ssid; return avc_has_perm(dsec1->sid, dsec2->sid, class, perms, NULL);}static int domain_has_evtchn(struct domain *d, struct evtchn *chn, u32 perms){ struct domain_security_struct *dsec; struct evtchn_security_struct *esec; dsec = d->ssid; esec = chn->ssid; return avc_has_perm(dsec->sid, esec->sid, SECCLASS_EVENT, perms, NULL);}static int domain_has_xen(struct domain *d, u32 perms){ struct domain_security_struct *dsec; dsec = d->ssid; return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, perms, NULL);}static int flask_domain_alloc_security(struct domain *d){ struct domain_security_struct *dsec; dsec = xmalloc(struct domain_security_struct); if ( !dsec ) return -ENOMEM; memset(dsec, 0, sizeof(struct domain_security_struct)); dsec->d = d; if ( d->domain_id == IDLE_DOMAIN_ID ) { dsec->sid = SECINITSID_XEN; dsec->create_sid = SECINITSID_DOM0; } else { dsec->sid = SECINITSID_UNLABELED; dsec->create_sid = SECSID_NULL; } d->ssid = dsec; return 0;}static void flask_domain_free_security(struct domain *d){ struct domain_security_struct *dsec = d->ssid; if ( !dsec ) return; d->ssid = NULL; xfree(dsec);}static int flask_evtchn_unbound(struct domain *d1, struct evtchn *chn, domid_t id2){ u32 newsid; int rc; domid_t id; struct domain *d2; struct domain_security_struct *dsec, *dsec1, *dsec2; struct evtchn_security_struct *esec; dsec = current->domain->ssid; dsec1 = d1->ssid; esec = chn->ssid; if ( id2 == DOMID_SELF ) id = current->domain->domain_id; else id = id2; d2 = get_domain_by_id(id); if ( d2 == NULL ) return -EPERM; dsec2 = d2->ssid; rc = security_transition_sid(dsec1->sid, dsec2->sid, SECCLASS_EVENT, &newsid); if ( rc ) goto out; rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT, EVENT__CREATE|EVENT__ALLOC, NULL); if ( rc ) goto out; rc = avc_has_perm(newsid, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, NULL); if ( rc ) goto out; else esec->sid = newsid;out: put_domain(d2); return rc;}static int flask_evtchn_interdomain(struct domain *d1, struct evtchn *chn1, struct domain *d2, struct evtchn *chn2){ u32 newsid1; u32 newsid2; int rc; struct domain_security_struct *dsec1, *dsec2; struct evtchn_security_struct *esec1, *esec2; dsec1 = d1->ssid; dsec2 = d2->ssid; esec1 = chn1->ssid; esec2 = chn2->ssid; rc = security_transition_sid(dsec1->sid, dsec2->sid, SECCLASS_EVENT, &newsid1); if ( rc ) { printk("%s: security_transition_sid failed, rc=%d (domain=%d)\n", __FUNCTION__, -rc, d2->domain_id); return rc; } rc = avc_has_perm(dsec1->sid, newsid1, SECCLASS_EVENT, EVENT__CREATE, NULL); if ( rc ) return rc; rc = security_transition_sid(dsec2->sid, dsec1->sid, SECCLASS_EVENT, &newsid2); if ( rc ) { printk("%s: security_transition_sid failed, rc=%d (domain=%d)\n", __FUNCTION__, -rc, d1->domain_id); return rc; } rc = avc_has_perm(dsec2->sid, newsid2, SECCLASS_EVENT, EVENT__CREATE, NULL); if ( rc ) return rc; rc = avc_has_perm(newsid1, dsec2->sid, SECCLASS_EVENT, EVENT__BIND, NULL); if ( rc ) return rc; rc = avc_has_perm(newsid2, dsec1->sid, SECCLASS_EVENT, EVENT__BIND, NULL); if ( rc ) return rc; esec1->sid = newsid1; esec2->sid = newsid2; return rc;}static void flask_evtchn_close_post(struct evtchn *chn){ struct evtchn_security_struct *esec; esec = chn->ssid; esec->sid = SECINITSID_UNLABELED;}static int flask_evtchn_send(struct domain *d, struct evtchn *chn){ return domain_has_evtchn(d, chn, EVENT__SEND);}static int flask_evtchn_status(struct domain *d, struct evtchn *chn){ return domain_has_evtchn(d, chn, EVENT__STATUS);}static int flask_evtchn_reset(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_EVENT, EVENT__RESET);}static int flask_alloc_security_evtchn(struct evtchn *chn){ struct evtchn_security_struct *esec; esec = xmalloc(struct evtchn_security_struct); if ( !esec ) return -ENOMEM; memset(esec, 0, sizeof(struct evtchn_security_struct)); esec->chn = chn; esec->sid = SECINITSID_UNLABELED; chn->ssid = esec; return 0; }static void flask_free_security_evtchn(struct evtchn *chn){ struct evtchn_security_struct *esec; if ( !chn ) return; esec = chn->ssid; if ( !esec ) return; chn->ssid = NULL; xfree(esec);}static int flask_grant_mapref(struct domain *d1, struct domain *d2, uint32_t flags){ u32 perms = GRANT__MAP_READ; if ( flags & GTF_writing ) perms |= GRANT__MAP_WRITE; return domain_has_perm(d1, d2, SECCLASS_GRANT, perms);}static int flask_grant_unmapref(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__UNMAP);}static int flask_grant_setup(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__SETUP);}static int flask_grant_transfer(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__TRANSFER);}static int flask_grant_copy(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_GRANT, GRANT__COPY);}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->sid; 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_translate_gpfn_list(struct domain *d, unsigned long mfn){ int rc = 0; u32 sid; struct domain_security_struct *dsec; dsec = d->ssid; rc = get_mfn_sid(mfn, &sid); if ( rc ) return rc; return avc_has_perm(dsec->sid, sid, SECCLASS_MMU, MMU__TRANSLATEGP, NULL);}static int flask_memory_adjust_reservation(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__ADJUST);}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){ 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);}/* Used to defer flushing of memory structures. */struct percpu_mm_info {#define DOP_FLUSH_TLB (1<<0) /* Flush the local TLB. */#define DOP_FLUSH_ALL_TLBS (1<<1) /* Flush TLBs of all VCPUs of current dom. */#define DOP_RELOAD_LDT (1<<2) /* Reload the LDT shadow mapping. */ unsigned int deferred_ops; /* If non-NULL, specifies a foreign subject domain for some operations. */ struct domain *foreign;};static DEFINE_PER_CPU(struct percpu_mm_info, percpu_mm_info);/* * Returns the current foreign domain; defaults to the currently-executing * domain if a foreign override hasn't been specified. */#define FOREIGNDOM (this_cpu(percpu_mm_info).foreign ?: current->domain)static int flask_console_io(struct domain *d, int cmd){ u32 perm; switch ( cmd ) { case CONSOLEIO_read: perm = XEN__READCONSOLE; break; case CONSOLEIO_write: perm = XEN__WRITECONSOLE; break; default: return -EPERM; } return domain_has_xen(d, perm);}static int flask_profile(struct domain *d, int op){ u32 perm; switch ( op ) { case XENOPROF_init: case XENOPROF_enable_virq: case XENOPROF_disable_virq: case XENOPROF_get_buffer: perm = XEN__NONPRIVPROFILE; break; case XENOPROF_reset_active_list: case XENOPROF_reset_passive_list: case XENOPROF_set_active: case XENOPROF_set_passive: case XENOPROF_reserve_counters: case XENOPROF_counter: case XENOPROF_setup_events: case XENOPROF_start: case XENOPROF_stop: case XENOPROF_release_counters: case XENOPROF_shutdown: perm = XEN__PRIVPROFILE; break; default: return -EPERM; } return domain_has_xen(d, perm);}static int flask_kexec(void){ return domain_has_xen(current->domain, XEN__KEXEC);}static int flask_schedop_shutdown(struct domain *d1, struct domain *d2){ return domain_has_perm(d1, d2, SECCLASS_DOMAIN, DOMAIN__SHUTDOWN);}static void flask_security_domaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info){ struct domain_security_struct *dsec; dsec = d->ssid; info->ssidref = dsec->sid;}static int flask_setvcpucontext(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT);}static int flask_pausedomain(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__PAUSE);}static int flask_unpausedomain(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__UNPAUSE);}static int flask_resumedomain(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__RESUME);}static int flask_domain_create(struct domain *d, u32 ssidref){ int rc; struct domain_security_struct *dsec1; struct domain_security_struct *dsec2; dsec1 = current->domain->ssid; if ( dsec1->create_sid == SECSID_NULL ) dsec1->create_sid = ssidref; rc = avc_has_perm(dsec1->sid, dsec1->create_sid, SECCLASS_DOMAIN, DOMAIN__CREATE, NULL); if ( rc ) { dsec1->create_sid = SECSID_NULL; return rc; } dsec2 = d->ssid; dsec2->sid = dsec1->create_sid; dsec1->create_sid = SECSID_NULL; dsec2->create_sid = SECSID_NULL; return rc;}static int flask_max_vcpus(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__MAX_VCPUS);}static int flask_destroydomain(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__DESTROY);}static int flask_vcpuaffinity(int cmd, struct domain *d){ u32 perm; switch ( cmd ) { case XEN_DOMCTL_setvcpuaffinity: perm = DOMAIN__SETVCPUAFFINITY; break; case XEN_DOMCTL_getvcpuaffinity: perm = DOMAIN__GETVCPUAFFINITY; break; default: return -EPERM; } return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm );}static int flask_scheduler(struct domain *d){ int rc = 0; rc = domain_has_xen(current->domain, XEN__SCHEDULER); if ( rc ) return rc; return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SCHEDULER);}static int flask_getdomaininfo(struct domain *d){ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__GETDOMAININFO);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -