################################################################################
#
# 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 domain_self_type;
attribute domain_target_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, mls_priv;

# Domain 0
declare_singleton_domain(dom0_t, mls_priv);

# I/O memory (DOMID_IO pseudo-domain)
type domio_t, xen_type;

# Xen heap (DOMID_XEN pseudo-domain)
type domxen_t, xen_type;

# Unlabeled objects
type unlabeled_t, xen_type;

# The XSM/FLASK security server
type security_t, xen_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;
type device_t, resource_type;

################################################################################
#
# Allow dom0 access to all sysctls, devices, and the security server.
#
# While this could be written more briefly using wildcards, the permissions are
# listed out to make removing specific permissions simpler.
#
################################################################################
allow dom0_t xen_t:xen {
	settime tbufcontrol readconsole clearconsole perfcontrol mtrr_add
	mtrr_del mtrr_read microcode physinfo quirk writeconsole readapic
	writeapic privprofile nonprivprofile kexec firmware sleep frequency
	getidle debug getcpuinfo heap pm_op mca_op lockprof cpupool_op tmem_op
	tmem_control getscheduler setscheduler
};
allow dom0_t xen_t:mmu memorymap;

# Allow dom0 to use these domctls on itself. For domctls acting on other
# domains, see the definitions of create_domain and manage_domain.
allow dom0_t dom0_t:domain {
	setvcpucontext max_vcpus setaffinity getaffinity getscheduler
	getdomaininfo getvcpuinfo getvcpucontext setdomainmaxmem setdomainhandle
	setdebugging hypercall settime setaddrsize getaddrsize trigger
	getextvcpucontext setextvcpucontext getvcpuextstate setvcpuextstate
	getpodtarget setpodtarget set_misc_info set_virq_handler
};
allow dom0_t dom0_t:domain2 {
	set_cpuid gettsc settsc setscheduler set_max_evtchn
};
allow dom0_t dom0_t:resource { add remove };

# These permissions allow using the FLASK security server to compute access
# checks locally, which could be used by a domain or service (such as xenstore)
# that does not have its own security server to make access decisions based on
# Xen's security policy.
allow dom0_t security_t:security {
	compute_av compute_create compute_member compute_relabel compute_user
};

# Allow string/SID conversions (for "xl list -Z" and similar)
allow dom0_t security_t:security check_context;

# Allow flask-label-pci to add and change labels
allow dom0_t security_t:security { add_ocontext del_ocontext };

# Allow performance parameters of the security server to be tweaked
allow dom0_t security_t:security setsecparam;

# Allow changing the security policy
allow dom0_t security_t:security { load_policy setenforce setbool };

# Audit policy change events even when they are allowed
auditallow dom0_t security_t:security { load_policy setenforce setbool };

admin_device(dom0_t, device_t)
admin_device(dom0_t, irq_t)
admin_device(dom0_t, ioport_t)
admin_device(dom0_t, iomem_t)

domain_comms(dom0_t, dom0_t)

# Allow all domains to use (unprivileged parts of) the tmem hypercall
allow domain_type xen_t:xen tmem_op;

###############################################################################
#
# Domain creation
#
###############################################################################

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)
domain_comms(domU_t, domU_t)
domain_self_comms(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)
domain_self_comms(isolated_domU_t)

# Declare a boolean that denies creation of prot_domU_t domains
gen_bool(prot_doms_locked, false)
declare_domain(prot_domU_t)
if (!prot_doms_locked) {
	create_domain(dom0_t, prot_domU_t)
}
domain_comms(dom0_t, prot_domU_t)
domain_comms(domU_t, prot_domU_t)
domain_comms(prot_domU_t, prot_domU_t)
domain_self_comms(prot_domU_t)

# domHVM_t is meant to be paired with a qemu-dm stub domain of type dm_dom_t
declare_domain(domHVM_t)
create_domain(dom0_t, domHVM_t)
manage_domain(dom0_t, domHVM_t)
domain_comms(dom0_t, domHVM_t)
domain_self_comms(domHVM_t)

declare_domain(dm_dom_t)
create_domain(dom0_t, dm_dom_t)
manage_domain(dom0_t, dm_dom_t)
domain_comms(dom0_t, dm_dom_t)
make_device_model(dom0_t, dm_dom_t, domHVM_t)

# nomigrate_t must be built via the nomigrate_t_building label; once built,
# dom0 cannot read its memory.
declare_domain(nomigrate_t)
declare_build_label(nomigrate_t)
create_domain_build_label(dom0_t, nomigrate_t)
manage_domain(dom0_t, nomigrate_t)
domain_comms(dom0_t, nomigrate_t)
domain_self_comms(nomigrate_t)

###############################################################################
#
# Device delegation
#
###############################################################################

type nic_dev_t, resource_type;

admin_device(dom0_t, nic_dev_t)
use_device(domU_t, nic_dev_t)

delegate_devices(dom0_t, domU_t)

###############################################################################
#
# 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.
#
###############################################################################

# label e1000e nic
#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: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: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

################################################################################
#
# Policy constraints
#
# Neverallow rules will cause the policy build to fail if an allow rule exists
# that violates the expression. This is used to ensure proper labeling of
# objects.
#
################################################################################

# Domains must be declared using domain_type
neverallow * ~domain_type:domain { create transition };

# Resources must be declared using resource_type
neverallow * ~resource_type:resource use;

# Events must use event_type (see create_channel for a template)
neverallow ~event_type *:event bind;
neverallow * ~event_type:event { create send status };

################################################################################
#
# Roles
#
################################################################################

# The object role (object_r) is used for devices, resources, and event channels;
# it does not need to be defined here and should not be used for domains.

# The system role is used for utility domains and pseudo-domains
role system_r;
role system_r types { xen_type domain_type };
# If you want to prevent domUs from being placed in system_r:
##role system_r types { xen_type dom0_t };

# The vm role is used for customer virtual machines
role vm_r;
role vm_r types { domain_type -dom0_t };
