diff mbox

[1/5] flask/policy: split into modules

Message ID 1464015933-26891-2-git-send-email-dgdegra@tycho.nsa.gov (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel De Graaf May 23, 2016, 3:05 p.m. UTC
This makes it easier to enable or disable parts of the XSM policy.

Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 tools/flask/policy/Makefile                        |  22 +-
 tools/flask/policy/modules/default_role.te         |   8 +
 tools/flask/policy/modules/dom0.te                 |  74 ++++++
 tools/flask/policy/modules/domU.te                 |  28 +++
 tools/flask/policy/modules/guest_features.te       |  31 +++
 tools/flask/policy/modules/isolated_domU.te        |   7 +
 tools/flask/policy/modules/modules.conf            |  37 +++
 tools/flask/policy/modules/nic_dev.te              |  14 ++
 tools/flask/policy/modules/nomigrate.te            |   8 +
 tools/flask/policy/modules/prot_domU.te            |  13 +
 .../policy/{policy/modules/xen => modules}/xen.if  |   0
 tools/flask/policy/modules/xen.te                  |  84 +++++++
 tools/flask/policy/policy/modules.conf             |  15 --
 tools/flask/policy/policy/modules/xen/xen.te       | 272 ---------------------
 14 files changed, 311 insertions(+), 302 deletions(-)
 create mode 100644 tools/flask/policy/modules/default_role.te
 create mode 100644 tools/flask/policy/modules/dom0.te
 create mode 100644 tools/flask/policy/modules/domU.te
 create mode 100644 tools/flask/policy/modules/guest_features.te
 create mode 100644 tools/flask/policy/modules/isolated_domU.te
 create mode 100644 tools/flask/policy/modules/modules.conf
 create mode 100644 tools/flask/policy/modules/nic_dev.te
 create mode 100644 tools/flask/policy/modules/nomigrate.te
 create mode 100644 tools/flask/policy/modules/prot_domU.te
 rename tools/flask/policy/{policy/modules/xen => modules}/xen.if (100%)
 create mode 100644 tools/flask/policy/modules/xen.te
 delete mode 100644 tools/flask/policy/policy/modules.conf
 delete mode 100644 tools/flask/policy/policy/modules/xen/xen.te

Comments

Konrad Rzeszutek Wilk June 7, 2016, 7:22 p.m. UTC | #1
On Mon, May 23, 2016 at 11:05:29AM -0400, Daniel De Graaf wrote:
> This makes it easier to enable or disable parts of the XSM policy.
> 

Hey Daniel,

I am no expert on this so please take it with a grain of salt.

.. snip..
> diff --git a/tools/flask/policy/modules/default_role.te b/tools/flask/policy/modules/default_role.te
> new file mode 100644
> index 0000000..74f870f
> --- /dev/null
> +++ b/tools/flask/policy/modules/default_role.te
> @@ -0,0 +1,8 @@
> +# Allow all domains to use system_r so that systems that are not using the
> +# user/role separation feature will work properly.
> +role system_r types domain_type;

In the 'original' code it also had : xen_type :

266 role system_r types { xen_type domain_type };                                   

Is this change done on purpose? Reading the xen.te it describes the 'system_r' as:
 "The system role is used for utility domains and pseudo-domains                "

which is .. confusing. What is an utility domain? Pseudo-domain?

[Looking in the new xen.te I see that it has the same syntax]
> +
> +# The vm role is used as part of user separation.  Allow all domain types to use
> +# this role except dom0.
> +role vm_r;
> +role vm_r types { domain_type -dom0_t };
> diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
> new file mode 100644
> index 0000000..dd4d7dd
> --- /dev/null
> +++ b/tools/flask/policy/modules/dom0.te
> @@ -0,0 +1,74 @@
> +################################################################################
> +#
> +# 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:xen2 {
> +	resource_op psr_cmt_op psr_cat_op pmu_ctrl get_symbol
> +	get_cpu_levelling_caps get_cpu_featureset xsplice_op

Hehe. livepatch_op now :-)

.. giant snip...

> diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
> new file mode 100644
> index 0000000..f374dc5
> --- /dev/null
> +++ b/tools/flask/policy/modules/xen.te
.. snip..

> +################################################################################
> +#
> +# 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.  If roles are
> +# not being used for separation, all domains can use the system role.
> +role system_r;
> +role system_r types { xen_type dom0_t };

Right here it is back again.

Is the 'default_role' neccessary then?


I've looked at the original xen.te and them splitting out to individual and there were no
missing copy-n-paste (except the above 'default_role.te' which I am not
clear about).

Thanks!
Daniel De Graaf June 7, 2016, 7:39 p.m. UTC | #2
On 06/07/2016 03:22 PM, Konrad Rzeszutek Wilk wrote:
> On Mon, May 23, 2016 at 11:05:29AM -0400, Daniel De Graaf wrote:
>> This makes it easier to enable or disable parts of the XSM policy.
>>
>
> Hey Daniel,
>
> I am no expert on this so please take it with a grain of salt.

That can actually be helpful to spot documentation problems :)

> .. snip..
>> diff --git a/tools/flask/policy/modules/default_role.te b/tools/flask/policy/modules/default_role.te
>> new file mode 100644
>> index 0000000..74f870f
>> --- /dev/null
>> +++ b/tools/flask/policy/modules/default_role.te
>> @@ -0,0 +1,8 @@
>> +# Allow all domains to use system_r so that systems that are not using the
>> +# user/role separation feature will work properly.
>> +role system_r types domain_type;
>
> In the 'original' code it also had : xen_type :
>
> 266 role system_r types { xen_type domain_type };
>
> Is this change done on purpose? Reading the xen.te it describes the 'system_r' as:
>  "The system role is used for utility domains and pseudo-domains                "
>
> which is .. confusing. What is an utility domain? Pseudo-domain?

Utility domains would be a domain that is not actually a part of a guest,
such as xenstore, vtpm-manager, and disaggregated components of dom0.

Pseudo-domain is the term used here to refer to DOMID_XEN and DOMID_IO.
Is there a better name for this?

> [Looking in the new xen.te I see that it has the same syntax]
>> +
>> +# The vm role is used as part of user separation.  Allow all domain types to use
>> +# this role except dom0.
>> +role vm_r;
>> +role vm_r types { domain_type -dom0_t };
>> diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
>> new file mode 100644
>> index 0000000..dd4d7dd
>> --- /dev/null
>> +++ b/tools/flask/policy/modules/dom0.te
>> @@ -0,0 +1,74 @@
>> +################################################################################
>> +#
>> +# 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:xen2 {
>> +	resource_op psr_cmt_op psr_cat_op pmu_ctrl get_symbol
>> +	get_cpu_levelling_caps get_cpu_featureset xsplice_op
>
> Hehe. livepatch_op now :-)
>

I have a corrected series that also has some other pending hypervisor
patches, which I can post whenever the 4.8 merging window is fully
open.

> .. giant snip...
>
>> diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
>> new file mode 100644
>> index 0000000..f374dc5
>> --- /dev/null
>> +++ b/tools/flask/policy/modules/xen.te
> .. snip..
>
>> +################################################################################
>> +#
>> +# 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.  If roles are
>> +# not being used for separation, all domains can use the system role.
>> +role system_r;
>> +role system_r types { xen_type dom0_t };
>
> Right here it is back again.
>
> Is the 'default_role' neccessary then?

Specifying some role is necessary to create a valid security label
(which is a user:role:type tuple).

The line in xen.te only allows the pseudo-domains and dom0 to use
system_r; this is a useful minimum, if you are going to place any
actual guests in another role.  If you include default_role.te,
then this expands to allowing all domains to use system_r.

I could split the default_role extraction into a separate patch if
you think this explanation belongs in a commit message.

> I've looked at the original xen.te and them splitting out to individual and there were no
> missing copy-n-paste (except the above 'default_role.te' which I am not
> clear about).
>
> Thanks!
>
Konrad Rzeszutek Wilk June 7, 2016, 7:57 p.m. UTC | #3
On Tue, Jun 07, 2016 at 03:39:59PM -0400, Daniel De Graaf wrote:
> On 06/07/2016 03:22 PM, Konrad Rzeszutek Wilk wrote:
> >On Mon, May 23, 2016 at 11:05:29AM -0400, Daniel De Graaf wrote:
> >>This makes it easier to enable or disable parts of the XSM policy.
> >>
> >
> >Hey Daniel,
> >
> >I am no expert on this so please take it with a grain of salt.
> 
> That can actually be helpful to spot documentation problems :)
> 
> >.. snip..
> >>diff --git a/tools/flask/policy/modules/default_role.te b/tools/flask/policy/modules/default_role.te
> >>new file mode 100644
> >>index 0000000..74f870f
> >>--- /dev/null
> >>+++ b/tools/flask/policy/modules/default_role.te
> >>@@ -0,0 +1,8 @@
> >>+# Allow all domains to use system_r so that systems that are not using the
> >>+# user/role separation feature will work properly.
> >>+role system_r types domain_type;
> >
> >In the 'original' code it also had : xen_type :
> >
> >266 role system_r types { xen_type domain_type };
> >
> >Is this change done on purpose? Reading the xen.te it describes the 'system_r' as:
> > "The system role is used for utility domains and pseudo-domains                "
> >
> >which is .. confusing. What is an utility domain? Pseudo-domain?
> 
> Utility domains would be a domain that is not actually a part of a guest,
> such as xenstore, vtpm-manager, and disaggregated components of dom0.

Ah, stubdomains!

Could there be an s/utility domain/utility domain (stubdomains)/ ?

> 
> Pseudo-domain is the term used here to refer to DOMID_XEN and DOMID_IO.
> Is there a better name for this?

Yes pls. That way it is easier to do a grep and find what it can refere to.

> 
> >[Looking in the new xen.te I see that it has the same syntax]
> >>+
> >>+# The vm role is used as part of user separation.  Allow all domain types to use
> >>+# this role except dom0.
> >>+role vm_r;
> >>+role vm_r types { domain_type -dom0_t };
> >>diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
> >>new file mode 100644
> >>index 0000000..dd4d7dd
> >>--- /dev/null
> >>+++ b/tools/flask/policy/modules/dom0.te
> >>@@ -0,0 +1,74 @@
> >>+################################################################################
> >>+#
> >>+# 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:xen2 {
> >>+	resource_op psr_cmt_op psr_cat_op pmu_ctrl get_symbol
> >>+	get_cpu_levelling_caps get_cpu_featureset xsplice_op
> >
> >Hehe. livepatch_op now :-)
> >
> 
> I have a corrected series that also has some other pending hypervisor
> patches, which I can post whenever the 4.8 merging window is fully
> open.

/me nods.
> 
> >.. giant snip...
> >
> >>diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
> >>new file mode 100644
> >>index 0000000..f374dc5
> >>--- /dev/null
> >>+++ b/tools/flask/policy/modules/xen.te
> >.. snip..
> >
> >>+################################################################################
> >>+#
> >>+# 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.  If roles are
> >>+# not being used for separation, all domains can use the system role.
> >>+role system_r;
> >>+role system_r types { xen_type dom0_t };
> >
> >Right here it is back again.
> >
> >Is the 'default_role' neccessary then?
> 
> Specifying some role is necessary to create a valid security label
> (which is a user:role:type tuple).
> 
> The line in xen.te only allows the pseudo-domains and dom0 to use
> system_r; this is a useful minimum, if you are going to place any
> actual guests in another role.  If you include default_role.te,
> then this expands to allowing all domains to use system_r.

Would it be better to rename 'default_role' to 'all_domains_access'
or such?

> 
> I could split the default_role extraction into a separate patch if
> you think this explanation belongs in a commit message.

It may be good for other newbies (like me) to get a gently introduction
via reading patches/code?
> 
> >I've looked at the original xen.te and them splitting out to individual and there were no
> >missing copy-n-paste (except the above 'default_role.te' which I am not
> >clear about).
> >
> >Thanks!
> >
> 
> 
> -- 
> Daniel De Graaf
> National Security Agency
diff mbox

Patch

diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile
index 4be921c..b2c2d06 100644
--- a/tools/flask/policy/Makefile
+++ b/tools/flask/policy/Makefile
@@ -37,7 +37,7 @@  POLICY_VER_LIST_HV = 24 30
 
 # policy source layout
 POLDIR := policy
-MODDIR := $(POLDIR)/modules
+MODDIR := modules
 
 # Classes and access vectors defined in the hypervisor. Changes to these require
 # a recompile of both the hypervisor and security policy.
@@ -60,7 +60,7 @@  DEV_OCONS := $(POLDIR)/device_contexts
 
 # config file paths
 GLOBALTUN := $(POLDIR)/global_tunables
-MOD_CONF := $(POLDIR)/modules.conf
+MOD_CONF := $(MODDIR)/modules.conf
 
 # checkpolicy can use the #line directives provided by -s for error reporting:
 M4PARAM := -D self_contained_policy -s
@@ -84,22 +84,14 @@  endif
 M4PARAM += -D mls_num_sens=$(MLS_SENS) -D mls_num_cats=$(MLS_CATS)
 
 
-# Find modules
-ALL_LAYERS := $(filter-out $(MODDIR)/CVS,$(shell find $(wildcard $(MODDIR)/*) -maxdepth 0 -type d))
-
-# sort here since it removes duplicates, which can happen
-# when a generated file is already generated
-DETECTED_MODS := $(sort $(foreach dir,$(ALL_LAYERS),$(wildcard $(dir)/*.te)))
-
 # modules.conf setting for policy configuration
 MODENABLED := on
 
 # extract settings from modules.conf
-ENABLED_MODS := $(foreach mod,$(shell awk '/^[ \t]*[a-z]/{ if ($$3 == "$(MODENABLED)") print $$1 }' $(MOD_CONF) 2> /dev/null),$(subst ./,,$(shell find -iname $(mod).te)))
-
-ALL_MODULES := $(filter $(ENABLED_MODS),$(DETECTED_MODS))
+ENABLED_LIST := $(shell awk '/^[ \t]*[a-z]/{ if ($$3 == "$(MODENABLED)") print $$1 }' $(MOD_CONF) 2> /dev/null)
 
-ALL_INTERFACES := $(ALL_MODULES:.te=.if)
+ALL_MODULES := $(foreach mod,$(ENABLED_LIST),$(MODDIR)/$(mod).te)
+ALL_INTERFACES := $(wildcard $(ALL_MODULES:.te=.if))
 
 # The order of these files is important
 POLICY_SECTIONS := $(SECCLASS) $(ISID_DECLS) $(AVS)
@@ -118,8 +110,8 @@  install: $(POLICY_FILENAME)
 $(POLICY_FILENAME): policy.conf
 	$(CHECKPOLICY) $(CHECKPOLICY_PARAM) $^ -o $@
 
-policy.conf: $(POLICY_SECTIONS)
-	$(M4) $(M4PARAM) $^ > $@
+policy.conf: $(POLICY_SECTIONS) $(MOD_CONF)
+	$(M4) $(M4PARAM) $(POLICY_SECTIONS) > $@
 
 clean:
 	$(RM) tmp policy.conf $(POLICY_FILENAME)
diff --git a/tools/flask/policy/modules/default_role.te b/tools/flask/policy/modules/default_role.te
new file mode 100644
index 0000000..74f870f
--- /dev/null
+++ b/tools/flask/policy/modules/default_role.te
@@ -0,0 +1,8 @@ 
+# Allow all domains to use system_r so that systems that are not using the
+# user/role separation feature will work properly.
+role system_r types domain_type;
+
+# The vm role is used as part of user separation.  Allow all domain types to use
+# this role except dom0.
+role vm_r;
+role vm_r types { domain_type -dom0_t };
diff --git a/tools/flask/policy/modules/dom0.te b/tools/flask/policy/modules/dom0.te
new file mode 100644
index 0000000..dd4d7dd
--- /dev/null
+++ b/tools/flask/policy/modules/dom0.te
@@ -0,0 +1,74 @@ 
+################################################################################
+#
+# 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:xen2 {
+	resource_op psr_cmt_op psr_cat_op pmu_ctrl get_symbol
+	get_cpu_levelling_caps get_cpu_featureset xsplice_op
+};
+
+# Allow dom0 to use all XENVER_ subops that have checks.
+# Note that dom0 is part of domain_type so this has duplicates.
+allow dom0_t xen_t:version {
+	xen_extraversion xen_compile_info xen_capabilities
+	xen_changeset xen_pagesize xen_guest_handle xen_commandline
+	xen_build_id
+};
+
+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 set_vnumainfo
+	get_vnumainfo psr_cmt_op psr_cat_op
+};
+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)
diff --git a/tools/flask/policy/modules/domU.te b/tools/flask/policy/modules/domU.te
new file mode 100644
index 0000000..b77df29
--- /dev/null
+++ b/tools/flask/policy/modules/domU.te
@@ -0,0 +1,28 @@ 
+###############################################################################
+#
+# 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)
+migrate_domain_out(dom0_t, domU_t)
+domain_self_comms(domU_t)
+
+# Device model for domU_t.  You can define distinct types for device models for
+# domains of other types, or add more make_device_model lines for this type.
+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, domU_t)
+
+# This is required for PCI (or other device) passthrough
+delegate_devices(dom0_t, domU_t)
+
+# Both of these domain types can be created using the default (system) role
+role system_r types { domU_t dm_dom_t };
diff --git a/tools/flask/policy/modules/guest_features.te b/tools/flask/policy/modules/guest_features.te
new file mode 100644
index 0000000..9ac9780
--- /dev/null
+++ b/tools/flask/policy/modules/guest_features.te
@@ -0,0 +1,31 @@ 
+# Allow all domains to use (unprivileged parts of) the tmem hypercall
+allow domain_type xen_t:xen tmem_op;
+
+# Allow all domains to use PMU (but not to change its settings --- that's what
+# pmu_ctrl is for)
+allow domain_type xen_t:xen2 pmu_use;
+
+# Allow guest console output to the serial console.  This is used by PV Linux
+# and stub domains for early boot output, so don't audit even when we deny it.
+# Without XSM, this is enabled only if the Xen was compiled in debug mode.
+gen_bool(guest_writeconsole, true)
+if (guest_writeconsole) {
+	allow domain_type xen_t : xen writeconsole;
+} else {
+	dontaudit domain_type xen_t : xen writeconsole;
+}
+
+# For normal guests, allow all queries except XENVER_commandline.
+allow domain_type xen_t:version {
+    xen_extraversion xen_compile_info xen_capabilities
+    xen_changeset xen_pagesize xen_guest_handle
+};
+
+# Version queries don't need auditing when denied.  They can be
+# encountered in normal operation by xl or by reading sysfs files in
+# Linux, so without this they will show up in the logs.  Since these
+# operations return valid responses (like "denied"), hiding the denials
+# should not break anything.
+dontaudit domain_type xen_t:version {
+	xen_commandline xen_build_id
+};
diff --git a/tools/flask/policy/modules/isolated_domU.te b/tools/flask/policy/modules/isolated_domU.te
new file mode 100644
index 0000000..4ee7689
--- /dev/null
+++ b/tools/flask/policy/modules/isolated_domU.te
@@ -0,0 +1,7 @@ 
+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)
+migrate_domain_out(dom0_t, isolated_domU_t)
+domain_self_comms(isolated_domU_t)
+
diff --git a/tools/flask/policy/modules/modules.conf b/tools/flask/policy/modules/modules.conf
new file mode 100644
index 0000000..5a1d905
--- /dev/null
+++ b/tools/flask/policy/modules/modules.conf
@@ -0,0 +1,37 @@ 
+#
+# This file contains a listing of available modules.
+#
+# To prevent a module from  being used in policy creation, set the module name
+# to "off"; otherwise, set the module name on "on".
+#
+# The order the modules appear in this file is the order they will be parsed;
+# this can be important if you plan to use types defined in one file in another.
+#
+
+# Basic types and classes for the Xen hypervisor.  This module is required.
+xen = on
+
+# Permissions for domain 0.  Most of these are required to boot.
+dom0 = on
+
+# Allow all domains the ability to use access-controlled features and hypercalls
+# that are not restricted when XSM is disabled.
+guest_features = on
+
+# The default domain type (domU_t) and its device model (dm_dom_t).  The domain
+# is created and managed by dom0_t, and has no special restrictions.
+#
+# This is required if you want to be able to create domains without specifying
+# their XSM label in the configuration.
+domU = on
+
+# Example types with restrictions
+isolated_domU = on
+prot_domU = on
+nomigrate = on
+
+# Example device policy.  Also see policy/device_contexts.
+nic_dev = on
+
+# Example roles.  Also see policy/users.
+default_role = on
diff --git a/tools/flask/policy/modules/nic_dev.te b/tools/flask/policy/modules/nic_dev.te
new file mode 100644
index 0000000..e0484af
--- /dev/null
+++ b/tools/flask/policy/modules/nic_dev.te
@@ -0,0 +1,14 @@ 
+###############################################################################
+#
+# Device delegation
+#
+# This requires that the device be labeled with a type defined here.  You can
+# use flask-label-pci to dynamically label devices on each boot or define the
+# labels statically in tools/flask/policy/policy/device_contexts
+#
+###############################################################################
+
+type nic_dev_t, resource_type;
+
+admin_device(dom0_t, nic_dev_t)
+use_device(domU_t, nic_dev_t)
diff --git a/tools/flask/policy/modules/nomigrate.te b/tools/flask/policy/modules/nomigrate.te
new file mode 100644
index 0000000..5b56caf
--- /dev/null
+++ b/tools/flask/policy/modules/nomigrate.te
@@ -0,0 +1,8 @@ 
+# Domains of type nomigrate_t must be built via the nomigrate_t_building label;
+# once built, dom0 cannot read their 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)
diff --git a/tools/flask/policy/modules/prot_domU.te b/tools/flask/policy/modules/prot_domU.te
new file mode 100644
index 0000000..a7c012c
--- /dev/null
+++ b/tools/flask/policy/modules/prot_domU.te
@@ -0,0 +1,13 @@ 
+# This is an alternative to nomigrate_t: a policy boolean controls the ability
+# to create or migrate a domain of type prot_domU_t.  If disabled, dom0 cannot
+# map memory belonging to those domains.
+gen_bool(prot_doms_locked, false)
+declare_domain(prot_domU_t)
+if (!prot_doms_locked) {
+	create_domain(dom0_t, prot_domU_t)
+	migrate_domain_out(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)
diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/modules/xen.if
similarity index 100%
rename from tools/flask/policy/policy/modules/xen/xen.if
rename to tools/flask/policy/modules/xen.if
diff --git a/tools/flask/policy/modules/xen.te b/tools/flask/policy/modules/xen.te
new file mode 100644
index 0000000..f374dc5
--- /dev/null
+++ b/tools/flask/policy/modules/xen.te
@@ -0,0 +1,84 @@ 
+################################################################################
+#
+# 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;
+
+################################################################################
+#
+# 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.  If roles are
+# not being used for separation, all domains can use the system role.
+role system_r;
+role system_r types { xen_type dom0_t };
diff --git a/tools/flask/policy/policy/modules.conf b/tools/flask/policy/policy/modules.conf
deleted file mode 100644
index 8043974..0000000
--- a/tools/flask/policy/policy/modules.conf
+++ /dev/null
@@ -1,15 +0,0 @@ 
-#
-# This file contains a listing of available modules.
-# To prevent a module from  being used in policy
-# creation, set the module name to "off" otherwise
-# set the module name on "on".
-#
-
-# Layer: xen
-# Module: xen
-# Required in base
-#
-# Policy for xen.
-# 
-xen = on
-
diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te
deleted file mode 100644
index 0b1c955..0000000
--- a/tools/flask/policy/policy/modules/xen/xen.te
+++ /dev/null
@@ -1,272 +0,0 @@ 
-################################################################################
-#
-# 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:xen2 {
-    resource_op
-    psr_cmt_op
-    psr_cat_op
-};
-allow dom0_t xen_t:xen2 {
-    pmu_ctrl
-    get_symbol
-    get_cpu_levelling_caps
-    get_cpu_featureset
-    xsplice_op
-};
-
-# Allow dom0 to use all XENVER_ subops that have checks.
-# Note that dom0 is part of domain_type so this has duplicates.
-allow dom0_t xen_t:version {
-    xen_extraversion xen_compile_info xen_capabilities
-    xen_changeset xen_pagesize xen_guest_handle xen_commandline
-    xen_build_id
-};
-
-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 set_vnumainfo
-	get_vnumainfo psr_cmt_op psr_cat_op
-};
-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;
-
-# Allow guest console output to the serial console.  This is used by PV Linux
-# and stub domains for early boot output, so don't audit even when we deny it.
-# Without XSM, this is enabled only if the Xen was compiled in debug mode.
-gen_bool(guest_writeconsole, true)
-if (guest_writeconsole) {
-	allow domain_type xen_t : xen writeconsole;
-} else {
-	dontaudit domain_type xen_t : xen writeconsole;
-}
-
-# Allow all domains to use PMU (but not to change its settings --- that's what
-# pmu_ctrl is for)
-allow domain_type xen_t:xen2 pmu_use;
-
-# For normal guests all possible except XENVER_commandline.
-allow domain_type xen_t:version {
-    xen_extraversion xen_compile_info xen_capabilities
-    xen_changeset xen_pagesize xen_guest_handle
-};
-
-# These queries don't need auditing when denied.  They can be
-# encountered in normal operation by xl or by reading sysfs files in
-# Linux, so without this they will show up in the logs.  Since these
-# operations return valid responses (like "denied"), hiding the denials
-# should not break anything.
-dontaudit domain_type xen_t:version {
-    xen_commandline xen_build_id
-};
-
-###############################################################################
-#
-# 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)
-migrate_domain_out(dom0_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)
-migrate_domain_out(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)
-	migrate_domain_out(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)
-
-# Device model for domU_t.  You can define distinct types for device models for
-# domains of other types, or add more make_device_model lines for this type.
-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, domU_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
-#
-# This requires that the device be labeled with a type defined here.  You can
-# use flask-label-pci to dynamically label devices on each boot or define the
-# labels statically in tools/flask/policy/policy/device_contexts
-#
-###############################################################################
-
-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)
-
-################################################################################
-#
-# 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 };