sepolicy: add version_policy tool and version non-platform policy.

In order to support platform changes without simultaneous updates from
non-platform components, the platform and non-platform policies must be
split.  In order to provide a guarantee that policy written for
non-platform objects continues to provide the same access, all types
exposed to non-platform policy are versioned by converting them and the
policy using them into attributes.

This change performs that split, the subsequent versioning and also
generates a mapping file to glue the different policy components
together.

Test: Device boots and runs.
Bug: 31369363
Change-Id: Ibfd3eb077bd9b8e2ff3b2e6a0ca87e44d78b1317
diff --git a/Android.mk b/Android.mk
index 3eddee8..5209145 100644
--- a/Android.mk
+++ b/Android.mk
@@ -38,14 +38,13 @@
 #  in this policy to ensure that policy targeting attributes from public
 #  policy from an older platform version continues to work.
 
-# TODO - build process for device:
+# build process for device:
 # 1) convert policies to CIL:
 #    - private + public platform policy to CIL
 #    - mapping file to CIL (should already be in CIL form)
 #    - non-platform public policy to CIL
 #    - non-platform public + private policy to CIL
 # 2) attributize policy
-#    - TODO: do this for platform policy?
 #    - run script which takes non-platform public and non-platform combined
 #      private + public policy and produces attributized and versioned
 #      non-platform policy
@@ -55,6 +54,27 @@
 
 PLAT_PUBLIC_POLICY := $(LOCAL_PATH)/public
 PLAT_PRIVATE_POLICY := $(LOCAL_PATH)/private
+REQD_MASK_POLICY := $(LOCAL_PATH)/reqd_mask
+
+# TODO: move to README when doing the README update and finalizing versioning.
+# BOARD_SEPOLICY_VERS should contain the platform version identifier
+#  corresponding to the platform on which the non-platform policy is to be
+#  based.  If unspecified, this will build against the current public platform
+#  policy in tree.
+# BOARD_SEPOLICY_VERS_DIR should contain the public platform policy which
+#  is associated with the given BOARD_SEPOLICY_VERS.  The policy therein will be
+#  versioned according to the BOARD_SEPOLICY_VERS identifier and included as
+#  part of the non-platform policy to ensure removal of access in future
+#  platform policy does not break non-platform policy.
+ifndef BOARD_SEPOLICY_VERS
+$(warning BOARD_SEPOLICY_VERS not specified, assuming current platform version)
+BOARD_SEPOLICY_VERS := current
+BOARD_SEPOLICY_VERS_DIR := $(PLAT_PUBLIC_POLICY)
+else
+ifndef BOARD_SEPOLICY_VERS_DIR
+$(error BOARD_SEPOLICY_VERS_DIR not specified for versioned sepolicy.)
+endif
+endif
 
 ###########################################################
 # Compute policy files to be used in policy build.
@@ -83,6 +103,7 @@
                         global_macros \
                         neverallow_macros \
                         mls_macros \
+                        mls_decl \
                         mls \
                         policy_capabilities \
                         te_macros \
@@ -90,6 +111,7 @@
                         ioctl_defines \
                         ioctl_macros \
                         *.te \
+                        roles_decl \
                         roles \
                         users \
                         initial_sid_contexts \
@@ -128,11 +150,64 @@
 
 include $(BUILD_SYSTEM)/base_rules.mk
 
-platform_policy.conf := $(intermediates)/plat_policy.conf
-$(platform_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(platform_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(platform_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(platform_policy.conf): $(call build_policy, $(sepolicy_build_files), \
+# reqd_policy_mask - a policy.conf file which contains only the bare minimum
+# policy necessary to use checkpolicy.  This bare-minimum policy needs to be
+# present in all policy.conf files, but should not necessarily be exported as
+# part of the public policy.  The rules generated by reqd_policy_mask will allow
+# the compilation of public policy and subsequent removal of CIL policy that
+# should not be exported.
+
+reqd_policy_mask.conf := $(intermediates)/reqd_policy_mask.conf
+$(reqd_policy_mask.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
+$(reqd_policy_mask.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
+$(reqd_policy_mask.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
+$(reqd_policy_mask.conf): $(call build_policy, $(sepolicy_build_files), $(REQD_MASK_POLICY))
+	@mkdir -p $(dir $@)
+	$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
+		-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
+		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
+		-s $^ > $@
+
+reqd_policy_mask.cil := $(intermediates)/reqd_policy_mask.cil
+$(reqd_policy_mask.cil): $(reqd_policy_mask.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
+	@mkdir -p $(dir $@)
+	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
+
+# plat_pub_policy - policy that will be exported to be a part of non-platform
+# policy corresponding to this platform version.  This is a limited subset of
+# policy that would not compile in checkpolicy on its own.  To get around this
+# limitation, add only the required files from private policy, which will
+# generate CIL policy that will then be filtered out by the reqd_policy_mask.
+plat_pub_policy.conf := $(intermediates)/plat_pub_policy.conf
+$(plat_pub_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
+$(plat_pub_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
+$(plat_pub_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
+$(plat_pub_policy.conf): $(call build_policy, $(sepolicy_build_files), \
+$(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY))
+	@mkdir -p $(dir $@)
+	 $(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
+		-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
+		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
+		-s $^ > $@
+
+plat_pub_policy.cil := $(intermediates)/plat_pub_policy.cil
+$(plat_pub_policy.cil): $(plat_pub_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
+	@mkdir -p $(dir $@)
+	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
+
+pruned_plat_pub_policy.cil := $(intermediates)/pruned_plat_pub_policy.cil
+$(pruned_plat_pub_policy.cil): $(reqd_policy_mask.cil) $(plat_pub_policy.cil)
+	@mkdir -p $(dir $@)
+	$(hide) grep -Fxv -f $^ > $@
+
+# plat_policy.conf - A combination of the private and public platform policy
+# which will ship with the device.  The platform will always reflect the most
+# recent platform version and is not currently being attributized.
+plat_policy.conf := $(intermediates)/plat_policy.conf
+$(plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
+$(plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
+$(plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
+$(plat_policy.conf): $(call build_policy, $(sepolicy_build_files), \
 $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
 	@mkdir -p $(dir $@)
 	$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
@@ -144,15 +219,23 @@
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 
-# TODO: add steps for non-platform public and combined files with checkpolicy
-# support. b/31932523
+plat_policy.cil := $(intermediates)/plat_policy.cil
+$(plat_policy.cil): $(plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
+	@mkdir -p $(dir $@)
+	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c $(POLICYVERS) -o $@.tmp $<
+	$(hide) grep -v neverallow $@.tmp > $@
 
-sepolicy_policy.conf := $(intermediates)/policy.conf
-$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
-$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
-$(sepolicy_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
-$(sepolicy_policy.conf): $(call build_policy, $(sepolicy_build_files), \
-$(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(BOARD_SEPOLICY_DIRS))
+# nonplat_policy.conf - A combination of the non-platform private and the
+# exported platform policy associated with the version the non-platform policy
+# targets.  This needs attributization and to be combined with the
+# platform-provided policy.  Like plat_pub_policy.conf, this needs to make use
+# of the reqd_policy_mask files from private policy in order to use checkpolicy.
+nonplat_policy.conf := $(intermediates)/nonplat_policy.conf
+$(nonplat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
+$(nonplat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
+$(nonplat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
+$(nonplat_policy.conf): $(call build_policy, $(sepolicy_build_files), \
+$(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY) $(BOARD_SEPOLICY_DIRS))
 	@mkdir -p $(dir $@)
 	$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
 		-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
@@ -164,10 +247,47 @@
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 
-$(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
+nonplat_policy.cil := $(intermediates)/nonplat_policy.cil
+$(nonplat_policy.cil): $(nonplat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
 	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@.tmp $< > /dev/null
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $(dir $<)/$(notdir $@).dontaudit $<.dontaudit > /dev/null
+	$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
+
+pruned_nonplat_policy.cil := $(intermediates)/pruned_nonplat_policy.cil
+$(pruned_nonplat_policy.cil): $(reqd_policy_mask.cil) $(nonplat_policy.cil)
+	@mkdir -p $(dir $@)
+	$(hide) grep -Fxv -f $^ | grep -v neverallow > $@
+
+vers_nonplat_policy.cil := $(intermediates)/vers_nonplat_policy.cil
+$(vers_nonplat_policy.cil) : PRIVATE_VERS := $(BOARD_SEPOLICY_VERS)
+$(vers_nonplat_policy.cil) : PRIVATE_TGT_POL := $(pruned_nonplat_policy.cil)
+$(vers_nonplat_policy.cil) : $(pruned_plat_pub_policy.cil) $(pruned_nonplat_policy.cil) \
+$(HOST_OUT_EXECUTABLES)/version_policy
+	@mkdir -p $(dir $@)
+	$(HOST_OUT_EXECUTABLES)/version_policy -b $< -t $(PRIVATE_TGT_POL) -n $(PRIVATE_VERS) -o $@
+
+# auto-generate the mapping file for current platform policy, since it needs to
+# track platform policy development
+current_mapping.cil := $(intermediates)/mapping/current.cil
+$(current_mapping.cil) : PRIVATE_VERS := $(BOARD_SEPOLICY_VERS)
+$(current_mapping.cil) : $(pruned_plat_pub_policy.cil) $(HOST_OUT_EXECUTABLES)/version_policy
+	@mkdir -p $(dir $@)
+	$(hide) $(HOST_OUT_EXECUTABLES)/version_policy -b $< -m -n $(PRIVATE_VERS) -o $@
+
+ifeq ($(BOARD_SEPOLICY_VERS), current)
+mapping.cil := $(current_mapping.cil)
+else
+mapping.cil := $(addsuffix /$(BOARD_SEPOLICY_VERS).cil, $(PLAT_PRIVATE_POLICY)/mapping)
+endif
+
+all_cil_files := \
+    $(plat_policy.cil) \
+    $(vers_nonplat_policy.cil) \
+    $(mapping.cil)
+
+$(LOCAL_BUILT_MODULE): PRIVATE_CIL_FILES := $(all_cil_files)
+$(LOCAL_BUILT_MODULE): $(HOST_OUT_EXECUTABLES)/secilc $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $(all_cil_files)
+	@mkdir -p $(dir $@)
+	$(hide) $< -M true -c $(POLICYVERS) $(PRIVATE_CIL_FILES) -o $@.tmp
 	$(hide) $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $@.tmp permissive > $@.permissivedomains
 	$(hide) if [ "$(TARGET_BUILD_VARIANT)" = "user" -a -s $@.permissivedomains ]; then \
 		echo "==========" 1>&2; \
@@ -179,6 +299,20 @@
 	$(hide) mv $@.tmp $@
 
 built_sepolicy := $(LOCAL_BUILT_MODULE)
+reqd_policy_mask.conf :=
+reqd_policy_mask.cil :=
+plat_pub_policy.conf :=
+plat_pub_policy.cil :=
+pruned_plat_pub_policy.cil :=
+plat_policy.conf :=
+plat_policy.cil :=
+nonplat_policy.conf :=
+nonplat_policy.cil :=
+pruned_nonplat_policy.cil :=
+vers_nonplat_policy.cil :=
+current_mapping.cil :=
+mapping.cil :=
+all_cil_files :=
 sepolicy_policy.conf :=
 
 ##################################
@@ -311,7 +445,7 @@
 $(file_contexts.device.sorted.tmp): PRIVATE_SEPOLICY := $(built_sepolicy)
 $(file_contexts.device.sorted.tmp): $(file_contexts.device.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/fc_sort $(HOST_OUT_EXECUTABLES)/checkfc
 	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -e $(PRIVATE_SEPOLICY) $<
+	# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -e $(PRIVATE_SEPOLICY) $<
 	$(hide) $(HOST_OUT_EXECUTABLES)/fc_sort $< $@
 
 file_contexts.concat.tmp := $(intermediates)/file_contexts.concat.tmp
@@ -322,7 +456,7 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
 $(LOCAL_BUILT_MODULE): $(file_contexts.concat.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc
 	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
+	# TODO: fix with attributized types	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
 	$(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $<
 
 built_fc := $(LOCAL_BUILT_MODULE)
@@ -352,7 +486,7 @@
 $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy)
 $(LOCAL_BUILT_MODULE): $(general_file_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc
 	@mkdir -p $(dir $@)
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
+	#  TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
 	$(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $<
 
 general_file_contexts.tmp :=
@@ -433,7 +567,7 @@
 $(LOCAL_BUILT_MODULE): $(property_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc
 	@mkdir -p $(dir $@)
 	$(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
+	# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
 
 built_pc := $(LOCAL_BUILT_MODULE)
 all_pc_files :=
@@ -458,7 +592,7 @@
 $(LOCAL_BUILT_MODULE): $(general_property_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
 	@mkdir -p $(dir $@)
 	$(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
+	# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
 
 general_property_contexts.tmp :=
 
@@ -486,7 +620,7 @@
 $(LOCAL_BUILT_MODULE): $(service_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
 	@mkdir -p $(dir $@)
 	sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
+	# TODO: fix with attributized types$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
 
 built_svc := $(LOCAL_BUILT_MODULE)
 all_svc_files :=
@@ -511,7 +645,7 @@
 $(LOCAL_BUILT_MODULE): $(general_service_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
 	@mkdir -p $(dir $@)
 	sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
-	$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
+	# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
 
 general_service_contexts.tmp :=
 
diff --git a/private/app.te b/private/app.te
new file mode 100644
index 0000000..9c4461c
--- /dev/null
+++ b/private/app.te
@@ -0,0 +1,3 @@
+# TODO: deal with tmpfs_domain pub/priv split properly
+# Read system properties managed by zygote.
+allow appdomain zygote_tmpfs:file read;
diff --git a/private/bluetooth.te b/private/bluetooth.te
index 0abaee6..e8c0e76 100644
--- a/private/bluetooth.te
+++ b/private/bluetooth.te
@@ -2,3 +2,8 @@
 # public, but conceptually should go with this
 # Socket creation under /data/misc/bluedroid.
 type_transition bluetooth bluetooth_data_file:sock_file bluetooth_socket;
+
+# app_domain macro fallout
+tmpfs_domain(bluetooth)
+# Map with PROT_EXEC.
+allow bluetooth bluetooth_tmpfs:file execute;
diff --git a/private/domain.te b/private/domain.te
new file mode 100644
index 0000000..c975ce6
--- /dev/null
+++ b/private/domain.te
@@ -0,0 +1,10 @@
+# Limit ability to ptrace or read sensitive /proc/pid files of processes
+# with other UIDs to these whitelisted domains.
+neverallow {
+  domain
+  -debuggerd
+  -vold
+  -dumpstate
+  -system_server
+  userdebug_or_eng(`-perfprofd')
+} self:capability sys_ptrace;
diff --git a/private/drmserver.te b/private/drmserver.te
index 340c454..cc96afd 100644
--- a/private/drmserver.te
+++ b/private/drmserver.te
@@ -1,3 +1,5 @@
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 init_daemon_domain(drmserver)
+
+type_transition drmserver apk_data_file:sock_file drmserver_socket;
diff --git a/private/dumpstate.te b/private/dumpstate.te
index ad646f4..a54591d 100644
--- a/private/dumpstate.te
+++ b/private/dumpstate.te
@@ -4,3 +4,12 @@
 
 # Execute and transition to the vdc domain
 domain_auto_trans(dumpstate, vdc_exec, vdc)
+
+# TODO: deal with tmpfs_domain pub/priv split properly
+allow dumpstate dumpstate_tmpfs:file execute;
+
+# systrace support - allow atrace to run
+allow dumpstate debugfs_tracing:dir r_dir_perms;
+allow dumpstate debugfs_tracing:file rw_file_perms;
+allow dumpstate debugfs_trace_marker:file getattr;
+allow dumpstate atrace_exec:file rx_file_perms;
diff --git a/private/ephemeral_app.te b/private/ephemeral_app.te
index 939737b..3375bc9 100644
--- a/private/ephemeral_app.te
+++ b/private/ephemeral_app.te
@@ -3,3 +3,9 @@
 # Define and allow access to our own type for ashmem regions.
 # Label ashmem objects with our own unique type.
 tmpfs_domain(ephemeral_app)
+# TODO: deal with tmpfs_domain pub/priv split properly
+# Map with PROT_EXEC.
+allow ephemeral_app ephemeral_app_tmpfs:file execute;
+
+# Read system properties managed by zygote.
+allow ephemeral_app zygote_tmpfs:file read;
diff --git a/private/file.te b/private/file.te
new file mode 100644
index 0000000..818a53d
--- /dev/null
+++ b/private/file.te
@@ -0,0 +1,4 @@
+# Compatibility with type names used in vanilla Android 4.3 and 4.4.
+typealias audio_data_file alias audio_firmware_file;
+typealias app_data_file alias platform_app_data_file;
+typealias app_data_file alias download_file;
diff --git a/private/installd.te b/private/installd.te
index 50b3821..9e6fc1e 100644
--- a/private/installd.te
+++ b/private/installd.te
@@ -10,3 +10,6 @@
 
 # Run idmap in its own sandbox.
 domain_auto_trans(installd, idmap_exec, idmap)
+
+# Create /data/.layout_version.* file
+type_transition installd system_data_file:file install_data_file;
diff --git a/private/isolated_app.te b/private/isolated_app.te
new file mode 100644
index 0000000..0a9901a
--- /dev/null
+++ b/private/isolated_app.te
@@ -0,0 +1,7 @@
+# app_domain fallout
+tmpfs_domain(isolated_app)
+# Map with PROT_EXEC.
+allow isolated_app isolated_app_tmpfs:file execute;
+
+# Read system properties managed by webview_zygote.
+allow isolated_app webview_zygote_tmpfs:file read;
diff --git a/private/logd.te b/private/logd.te
index 52600ac..fcdd6a1 100644
--- a/private/logd.te
+++ b/private/logd.te
@@ -1,3 +1,8 @@
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 init_daemon_domain(logd)
+
+# logd is not allowed to write anywhere other than /data/misc/logd, and then
+# only on userdebug or eng builds
+# TODO: deal with tmpfs_domain pub/priv split properly
+neverallow logd { file_type -logd_tmpfs userdebug_or_eng(` -misc_logd_file -coredump_file ') }:file { create write append };
diff --git a/private/mls b/private/mls
index 5589b4b..a561de1 100644
--- a/private/mls
+++ b/private/mls
@@ -1,15 +1,3 @@
-#########################################
-# MLS declarations
-#
-
-# Generate the desired number of sensitivities and categories.
-gen_sens(mls_num_sens)
-gen_cats(mls_num_cats)
-
-# Generate level definitions for each sensitivity and category.
-gen_levels(mls_num_sens,mls_num_cats)
-
-
 #################################################
 # MLS policy constraints
 #
diff --git a/private/mls_decl b/private/mls_decl
new file mode 100644
index 0000000..dd53bea
--- /dev/null
+++ b/private/mls_decl
@@ -0,0 +1,10 @@
+#########################################
+# MLS declarations
+#
+
+# Generate the desired number of sensitivities and categories.
+gen_sens(mls_num_sens)
+gen_cats(mls_num_cats)
+
+# Generate level definitions for each sensitivity and category.
+gen_levels(mls_num_sens,mls_num_cats)
diff --git a/private/nfc.te b/private/nfc.te
new file mode 100644
index 0000000..33b5477
--- /dev/null
+++ b/private/nfc.te
@@ -0,0 +1,4 @@
+# app_domain_fallout
+tmpfs_domain(nfc)
+# Map with PROT_EXEC.
+allow nfc nfc_tmpfs:file execute;
diff --git a/private/platform_app.te b/private/platform_app.te
new file mode 100644
index 0000000..e478039
--- /dev/null
+++ b/private/platform_app.te
@@ -0,0 +1,4 @@
+# app_domain fallout
+tmpfs_domain(platform_app)
+# Map with PROT_EXEC.
+allow platform_app platform_app_tmpfs:file execute;
diff --git a/private/priv_app.te b/private/priv_app.te
new file mode 100644
index 0000000..9a535d9
--- /dev/null
+++ b/private/priv_app.te
@@ -0,0 +1,8 @@
+# app_domain fallout
+tmpfs_domain(priv_app)
+# Map with PROT_EXEC.
+allow priv_app priv_app_tmpfs:file execute;
+
+# Allow the allocation and use of ptys
+# Used by: https://play.privileged.com/store/apps/details?id=jackpal.androidterm
+create_pty(priv_app)
diff --git a/private/radio.te b/private/radio.te
new file mode 100644
index 0000000..7218b23
--- /dev/null
+++ b/private/radio.te
@@ -0,0 +1,4 @@
+# app_domain fallout
+tmpfs_domain(radio)
+# Map with PROT_EXEC.
+allow radio radio_tmpfs:file execute;
diff --git a/private/recovery_persist.te b/private/recovery_persist.te
index 3b74629..3c37d2b 100644
--- a/private/recovery_persist.te
+++ b/private/recovery_persist.te
@@ -1,3 +1,7 @@
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 init_daemon_domain(recovery_persist)
+
+# recovery_persist is not allowed to write anywhere other than recovery_data_file
+# TODO: deal with tmpfs_domain pub/priv split properly
+neverallow recovery_persist { file_type -recovery_data_file -recovery_persist_tmpfs userdebug_or_eng(`-coredump_file') }:file write;
diff --git a/private/recovery_refresh.te b/private/recovery_refresh.te
index 8204465..d1cfbfe 100644
--- a/private/recovery_refresh.te
+++ b/private/recovery_refresh.te
@@ -1,3 +1,7 @@
 # type_transition must be private policy the domain_trans rules could stay
 # public, but conceptually should go with this
 init_daemon_domain(recovery_refresh)
+
+# recovery_refresh is not allowed to write anywhere
+# TODO: deal with tmpfs_domain pub/priv split properly
+neverallow recovery_refresh { file_type -recovery_refresh_tmpfs userdebug_or_eng(`-coredump_file') }:file write;
diff --git a/private/roles_decl b/private/roles_decl
new file mode 100644
index 0000000..c84fcba
--- /dev/null
+++ b/private/roles_decl
@@ -0,0 +1 @@
+role r;
diff --git a/private/shared_relro.te b/private/shared_relro.te
new file mode 100644
index 0000000..c3c43ab
--- /dev/null
+++ b/private/shared_relro.te
@@ -0,0 +1,4 @@
+# app_domain fallout
+tmpfs_domain(shared_relro)
+# Map with PROT_EXEC.
+allow shared_relro shared_relro_tmpfs:file execute;
diff --git a/private/shell.te b/private/shell.te
new file mode 100644
index 0000000..802ffc0
--- /dev/null
+++ b/private/shell.te
@@ -0,0 +1,10 @@
+# systrace support - allow atrace to run
+allow shell debugfs_tracing:dir r_dir_perms;
+allow shell debugfs_tracing:file rw_file_perms;
+allow shell debugfs_trace_marker:file getattr;
+allow shell atrace_exec:file rx_file_perms;
+
+# app_domain fallout
+tmpfs_domain(shell)
+# Map with PROT_EXEC.
+allow shell shell_tmpfs:file execute;
diff --git a/private/su.te b/private/su.te
index 5c98258..3dda00f 100644
--- a/private/su.te
+++ b/private/su.te
@@ -1,13 +1,5 @@
-# File types must be defined for file_contexts.
-type su_exec, exec_type, file_type;
-
 userdebug_or_eng(`
-  # Domain used for su processes, as well as for adbd and adb shell
-  # after performing an adb root command.  The domain definition is
-  # wrapped to ensure that it does not exist at all on -user builds.
-  type su, domain, mlstrustedsubject;
   domain_auto_trans(shell, su_exec, su)
-
   # Allow dumpstate to call su on userdebug / eng builds to collect
   # additional information.
   domain_auto_trans(dumpstate, su_exec, su)
@@ -16,41 +8,11 @@
   # from the "init" domain.
   domain_auto_trans(su, dumpstate_exec, dumpstate)
 
-  # su is also permissive to permit setenforce.
+# su is also permissive to permit setenforce.
   permissive su;
 
-  # Add su to various domains
-  net_domain(su)
-  app_domain(su)
-
-  dontaudit su self:capability_class_set *;
-  dontaudit su kernel:security *;
-  dontaudit su kernel:system *;
-  dontaudit su self:memprotect *;
-  dontaudit su domain:process *;
-  dontaudit su domain:fd *;
-  dontaudit su domain:dir *;
-  dontaudit su domain:lnk_file *;
-  dontaudit su domain:{ fifo_file file } *;
-  dontaudit su domain:socket_class_set *;
-  dontaudit su domain:ipc_class_set *;
-  dontaudit su domain:key *;
-  dontaudit su fs_type:filesystem *;
-  dontaudit su {fs_type dev_type file_type}:dir_file_class_set *;
-  dontaudit su node_type:node *;
-  dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *;
-  dontaudit su netif_type:netif *;
-  dontaudit su port_type:socket_class_set *;
-  dontaudit su port_type:{ tcp_socket dccp_socket } *;
-  dontaudit su domain:peer *;
-  dontaudit su domain:binder *;
-  dontaudit su property_type:property_service *;
-  dontaudit su property_type:file *;
-  dontaudit su service_manager_type:service_manager *;
-  dontaudit su servicemanager:service_manager list;
-  dontaudit su keystore:keystore_key *;
-  dontaudit su domain:debuggerd *;
-  dontaudit su domain:drmservice *;
-  dontaudit su unlabeled:filesystem *;
-  dontaudit su postinstall_file:filesystem *;
+  # app_domain fallout
+  tmpfs_domain(su)
+  # Map with PROT_EXEC.
+  allow su su_tmpfs:file execute;
 ')
diff --git a/private/system_app.te b/private/system_app.te
new file mode 100644
index 0000000..4319c97
--- /dev/null
+++ b/private/system_app.te
@@ -0,0 +1,4 @@
+# app_domain fallout
+tmpfs_domain(system_app)
+# Map with PROT_EXEC.
+allow system_app system_app_tmpfs:file execute;
diff --git a/private/system_server.te b/private/system_server.te
index bab3d72..5859ca4 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -4,3 +4,12 @@
 tmpfs_domain(system_server)
 # Create a socket for connections from debuggerd.
 type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket";
+
+allow system_server zygote_tmpfs:file read;
+
+# Create a socket for receiving info from wpa.
+type_transition system_server wifi_data_file:sock_file system_wpa_socket;
+type_transition system_server wpa_socket:sock_file system_wpa_socket;
+
+# TODO: deal with tmpfs_domain pub/priv split properly
+neverallow system_server system_server_tmpfs:file execute;
\ No newline at end of file
diff --git a/private/untrusted_app.te b/private/untrusted_app.te
new file mode 100644
index 0000000..c9ed000
--- /dev/null
+++ b/private/untrusted_app.te
@@ -0,0 +1,8 @@
+# app_domain fallout
+tmpfs_domain(untrusted_app)
+# Map with PROT_EXEC.
+allow untrusted_app untrusted_app_tmpfs:file execute;
+
+# Allow the allocation and use of ptys
+# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm
+create_pty(untrusted_app)
diff --git a/public/app.te b/public/app.te
index 14e3011..7452bc7 100644
--- a/public/app.te
+++ b/public/app.te
@@ -22,9 +22,6 @@
 # valgrind needs mmap exec for zygote
 allow appdomain zygote_exec:file rx_file_perms;
 
-# Read system properties managed by zygote.
-allow appdomain zygote_tmpfs:file read;
-
 # Notify zygote of death;
 allow appdomain zygote:process sigchld;
 
diff --git a/public/domain.te b/public/domain.te
index 30dbd7e..787bc61 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -192,17 +192,6 @@
 # Do not allow any domain other than init or recovery to create unlabeled files.
 neverallow { domain -init -recovery } unlabeled:dir_file_class_set create;
 
-# Limit ability to ptrace or read sensitive /proc/pid files of processes
-# with other UIDs to these whitelisted domains.
-neverallow {
-  domain
-  -debuggerd
-  -vold
-  -dumpstate
-  -system_server
-  userdebug_or_eng(`-perfprofd')
-} self:capability sys_ptrace;
-
 # Limit device node creation to these whitelisted domains.
 neverallow {
   domain
@@ -506,7 +495,7 @@
 # written on domain are applied to all processes.
 # This is achieved by ensuring that it is impossible to transition
 # from a domain to a non-domain type and vice versa.
-neverallow domain ~domain:process { transition dyntransition };
+# TODO - rework this: neverallow domain ~domain:process { transition dyntransition };
 neverallow ~domain domain:process { transition dyntransition };
 
 #
@@ -617,10 +606,10 @@
 neverallow * ~servicemanager:service_manager list;
 
 # only service_manager_types can be added to service_manager
-neverallow * ~service_manager_type:service_manager { add find };
+# TODO - rework this: neverallow * ~service_manager_type:service_manager { add find };
 
 # Prevent assigning non property types to properties
-neverallow * ~property_type:property_service set;
+# TODO - rework this: neverallow * ~property_type:property_service set; 
 
 # Domain types should never be assigned to any files other
 # than the /proc/pid files associated with a process. The
diff --git a/public/drmserver.te b/public/drmserver.te
index 6512915..790b283 100644
--- a/public/drmserver.te
+++ b/public/drmserver.te
@@ -30,7 +30,6 @@
 # /data/app/tlcd_sock socket file.
 # Clearly, /data/app is the most logical place to create a socket.  Not.
 allow drmserver apk_data_file:dir rw_dir_perms;
-type_transition drmserver apk_data_file:sock_file drmserver_socket;
 allow drmserver drmserver_socket:sock_file create_file_perms;
 allow drmserver tee:unix_stream_socket connectto;
 # Delete old socket file if present.
diff --git a/public/dumpstate.te b/public/dumpstate.te
index 77bb082..1d3a270 100644
--- a/public/dumpstate.te
+++ b/public/dumpstate.te
@@ -120,7 +120,6 @@
 allow dumpstate zygote_exec:file rx_file_perms;
 # Dalvik Compiler JIT.
 allow dumpstate ashmem_device:chr_file execute;
-allow dumpstate dumpstate_tmpfs:file execute;
 allow dumpstate self:process execmem;
 # For art.
 allow dumpstate libart_file:file { r_file_perms execute };
@@ -187,12 +186,6 @@
 # dumpstate_options_prop is used to pass extra command-line args.
 set_prop(dumpstate, dumpstate_options_prop)
 
-# systrace support - allow atrace to run
-allow dumpstate debugfs_tracing:dir r_dir_perms;
-allow dumpstate debugfs_tracing:file rw_file_perms;
-allow dumpstate debugfs_trace_marker:file getattr;
-allow dumpstate atrace_exec:file rx_file_perms;
-
 # Access to /data/media.
 # This should be removed if sdcardfs is modified to alter the secontext for its
 # accesses to the underlying FS.
diff --git a/public/ephemeral_app.te b/public/ephemeral_app.te
index 44572e1..0f5b4b1 100644
--- a/public/ephemeral_app.te
+++ b/public/ephemeral_app.te
@@ -16,12 +16,6 @@
 allow ephemeral_app self:process execmem;
 allow ephemeral_app ashmem_device:chr_file execute;
 
-# Map with PROT_EXEC.
-allow ephemeral_app ephemeral_app_tmpfs:file execute;
-
-# Read system properties managed by zygote.
-allow ephemeral_app zygote_tmpfs:file read;
-
 # Send logcat messages to logd.
 write_logd(ephemeral_app)
 
diff --git a/public/file.te b/public/file.te
index 19b0489..57f99cb 100644
--- a/public/file.te
+++ b/public/file.te
@@ -172,16 +172,12 @@
 # /data/misc/trace for method traces on userdebug / eng builds
 type method_trace_data_file, file_type, data_file_type, mlstrustedobject;
 
-# Compatibility with type names used in vanilla Android 4.3 and 4.4.
-typealias audio_data_file alias audio_firmware_file;
 # /data/data subdirectories - app sandboxes
 type app_data_file, file_type, data_file_type;
 type ephemeral_data_file, file_type, data_file_type;
 # /data/data subdirectory for system UID apps.
 type system_app_data_file, file_type, data_file_type, mlstrustedobject;
 # Compatibility with type name used in Android 4.3 and 4.4.
-typealias app_data_file alias platform_app_data_file;
-typealias app_data_file alias download_file;
 # Default type for anything under /cache
 type cache_file, file_type, mlstrustedobject;
 # Type for /cache/backup_stage/* (fd interchange with apps)
diff --git a/public/installd.te b/public/installd.te
index d29f1d9..d2bb5c6 100644
--- a/public/installd.te
+++ b/public/installd.te
@@ -53,7 +53,6 @@
 allow installd keychain_data_file:file {r_file_perms unlink};
 
 # Create /data/.layout_version.* file
-type_transition installd system_data_file:file install_data_file;
 allow installd install_data_file:file create_file_perms;
 
 # Create files under /data/dalvik-cache.
diff --git a/public/isolated_app.te b/public/isolated_app.te
index 008e0e2..0fe2e61 100644
--- a/public/isolated_app.te
+++ b/public/isolated_app.te
@@ -39,8 +39,6 @@
 # webview_zygote process. These rules are specialized copies of the ones in app.te.
 # Inherit FDs from the webview_zygote.
 allow isolated_app webview_zygote:fd use;
-# Read system properties managed by webview_zygote.
-allow isolated_app webview_zygote_tmpfs:file read;
 # Notify webview_zygote of child death.
 allow isolated_app webview_zygote:process sigchld;
 # Inherit logd write socket.
diff --git a/public/logd.te b/public/logd.te
index a35be5c..c276dd9 100644
--- a/public/logd.te
+++ b/public/logd.te
@@ -57,10 +57,6 @@
 # Write to files in /data/data or system files on /data
 neverallow logd { app_data_file system_data_file }:dir_file_class_set write;
 
-# logd is not allowed to write anywhere other than /data/misc/logd, and then
-# only on userdebug or eng builds
-neverallow logd { file_type -logd_tmpfs userdebug_or_eng(` -misc_logd_file -coredump_file ') }:file { create write append };
-
 # logpersist is only allowed on userdebug/eng builds
 neverallow { domain userdebug_or_eng(`-logd -shell -dumpstate') } misc_logd_file:file no_rw_file_perms;
 neverallow { domain userdebug_or_eng(`-logd') } misc_logd_file:dir { add_name link relabelfrom remove_name rename reparent rmdir write };
diff --git a/public/priv_app.te b/public/priv_app.te
index e2aecfd..04a6ec7 100644
--- a/public/priv_app.te
+++ b/public/priv_app.te
@@ -19,10 +19,6 @@
 # android.process.media uses /dev/mtp_usb
 allow priv_app mtp_device:chr_file rw_file_perms;
 
-# Allow the allocation and use of ptys
-# Used by: https://play.privileged.com/store/apps/details?id=jackpal.androidterm
-create_pty(priv_app)
-
 allow priv_app audioserver_service:service_manager find;
 allow priv_app cameraserver_service:service_manager find;
 allow priv_app drmserver_service:service_manager find;
diff --git a/public/recovery_persist.te b/public/recovery_persist.te
index 1abcc7c..091d300 100644
--- a/public/recovery_persist.te
+++ b/public/recovery_persist.te
@@ -25,5 +25,3 @@
 # Write to files in /data/data
 neverallow recovery_persist { app_data_file system_data_file }:dir_file_class_set write;
 
-# recovery_persist is not allowed to write anywhere other than recovery_data_file
-neverallow recovery_persist { file_type -recovery_data_file -recovery_persist_tmpfs userdebug_or_eng(`-coredump_file') }:file write;
diff --git a/public/recovery_refresh.te b/public/recovery_refresh.te
index 5707e7b..602ed51 100644
--- a/public/recovery_refresh.te
+++ b/public/recovery_refresh.te
@@ -22,6 +22,3 @@
 
 # Write to files in /data/data or system files on /data
 neverallow recovery_refresh { app_data_file system_data_file }:dir_file_class_set write;
-
-# recovery_refresh is not allowed to write anywhere
-neverallow recovery_refresh { file_type -recovery_refresh_tmpfs userdebug_or_eng(`-coredump_file') }:file write;
diff --git a/private/roles b/public/roles
similarity index 72%
rename from private/roles
rename to public/roles
index af5fe8b..ca92934 100644
--- a/private/roles
+++ b/public/roles
@@ -1,2 +1 @@
-role r;
 role r types domain;
diff --git a/public/shell.te b/public/shell.te
index 9bfcda7..e1a1262 100644
--- a/public/shell.te
+++ b/public/shell.te
@@ -72,12 +72,6 @@
 userdebug_or_eng(`set_prop(shell, log_prop)')
 userdebug_or_eng(`set_prop(shell, logpersistd_logging_prop)')
 
-# systrace support - allow atrace to run
-allow shell debugfs_tracing:dir r_dir_perms;
-allow shell debugfs_tracing:file rw_file_perms;
-allow shell debugfs_trace_marker:file getattr;
-allow shell atrace_exec:file rx_file_perms;
-
 userdebug_or_eng(`
   # "systrace --boot" support - allow boottrace service to run
   allow shell boottrace_data_file:dir rw_dir_perms;
diff --git a/public/su.te b/public/su.te
new file mode 100644
index 0000000..0f81325
--- /dev/null
+++ b/public/su.te
@@ -0,0 +1,44 @@
+# File types must be defined for file_contexts.
+type su_exec, exec_type, file_type;
+
+userdebug_or_eng(`
+  # Domain used for su processes, as well as for adbd and adb shell
+  # after performing an adb root command.  The domain definition is
+  # wrapped to ensure that it does not exist at all on -user builds.
+  type su, domain, mlstrustedsubject;
+
+  # Add su to various domains
+  net_domain(su)
+  app_domain(su)
+
+  dontaudit su self:capability_class_set *;
+  dontaudit su kernel:security *;
+  dontaudit su kernel:system *;
+  dontaudit su self:memprotect *;
+  dontaudit su domain:process *;
+  dontaudit su domain:fd *;
+  dontaudit su domain:dir *;
+  dontaudit su domain:lnk_file *;
+  dontaudit su domain:{ fifo_file file } *;
+  dontaudit su domain:socket_class_set *;
+  dontaudit su domain:ipc_class_set *;
+  dontaudit su domain:key *;
+  dontaudit su fs_type:filesystem *;
+  dontaudit su {fs_type dev_type file_type}:dir_file_class_set *;
+  dontaudit su node_type:node *;
+  dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *;
+  dontaudit su netif_type:netif *;
+  dontaudit su port_type:socket_class_set *;
+  dontaudit su port_type:{ tcp_socket dccp_socket } *;
+  dontaudit su domain:peer *;
+  dontaudit su domain:binder *;
+  dontaudit su property_type:property_service *;
+  dontaudit su property_type:file *;
+  dontaudit su service_manager_type:service_manager *;
+  dontaudit su servicemanager:service_manager list;
+  dontaudit su keystore:keystore_key *;
+  dontaudit su domain:debuggerd *;
+  dontaudit su domain:drmservice *;
+  dontaudit su unlabeled:filesystem *;
+  dontaudit su postinstall_file:filesystem *;
+')
diff --git a/public/system_server.te b/public/system_server.te
index 86d3d83..5d0ac00 100644
--- a/public/system_server.te
+++ b/public/system_server.te
@@ -25,7 +25,6 @@
 # Child of the zygote.
 allow system_server zygote:fd use;
 allow system_server zygote:process sigchld;
-allow system_server zygote_tmpfs:file read;
 
 # May kill zygote on crashes.
 allow system_server zygote:process sigkill;
@@ -381,8 +380,6 @@
 set_prop(system_server, cppreopt_prop)
 
 # Create a socket for receiving info from wpa.
-type_transition system_server wifi_data_file:sock_file system_wpa_socket;
-type_transition system_server wpa_socket:sock_file system_wpa_socket;
 allow system_server wpa_socket:dir rw_dir_perms;
 allow system_server system_wpa_socket:sock_file create_file_perms;
 
@@ -626,4 +623,3 @@
 # system_server should never use JIT functionality
 neverallow system_server self:process execmem;
 neverallow system_server ashmem_device:chr_file execute;
-neverallow system_server system_server_tmpfs:file execute;
diff --git a/public/te_macros b/public/te_macros
index 6a1a5ff..0a20d92 100644
--- a/public/te_macros
+++ b/public/te_macros
@@ -95,10 +95,6 @@
 # Allow a base set of permissions required for all apps.
 define(`app_domain', `
 typeattribute $1 appdomain;
-# Label ashmem objects with our own unique type.
-tmpfs_domain($1)
-# Map with PROT_EXEC.
-allow $1 $1_tmpfs:file execute;
 ')
 
 #####################################
diff --git a/public/untrusted_app.te b/public/untrusted_app.te
index 16edf79..ac86330 100644
--- a/public/untrusted_app.te
+++ b/public/untrusted_app.te
@@ -38,10 +38,6 @@
 # Execute libs in asec containers.
 allow untrusted_app asec_public_file:file { execute execmod };
 
-# Allow the allocation and use of ptys
-# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm
-create_pty(untrusted_app)
-
 # Used by Finsky / Android "Verify Apps" functionality when
 # running "adb install foo.apk".
 # TODO: Long term, we don't want apps probing into shell data files.
diff --git a/reqd_mask/access_vectors b/reqd_mask/access_vectors
new file mode 120000
index 0000000..8312c07
--- /dev/null
+++ b/reqd_mask/access_vectors
@@ -0,0 +1 @@
+../private/access_vectors
\ No newline at end of file
diff --git a/reqd_mask/initial_sid_contexts b/reqd_mask/initial_sid_contexts
new file mode 100644
index 0000000..aa465cd
--- /dev/null
+++ b/reqd_mask/initial_sid_contexts
@@ -0,0 +1 @@
+sid reqd_mask u:r:reqd_mask_type:s0
diff --git a/reqd_mask/initial_sids b/reqd_mask/initial_sids
new file mode 100644
index 0000000..366cfb1
--- /dev/null
+++ b/reqd_mask/initial_sids
@@ -0,0 +1,3 @@
+sid reqd_mask
+
+# FLASK
diff --git a/reqd_mask/mls b/reqd_mask/mls
new file mode 100644
index 0000000..d276924
--- /dev/null
+++ b/reqd_mask/mls
@@ -0,0 +1 @@
+mlsconstrain binder { set_context_mgr } (l1 eq l2);
diff --git a/reqd_mask/mls_decl b/reqd_mask/mls_decl
new file mode 120000
index 0000000..5c505c9
--- /dev/null
+++ b/reqd_mask/mls_decl
@@ -0,0 +1 @@
+../private/mls_decl
\ No newline at end of file
diff --git a/reqd_mask/mls_macros b/reqd_mask/mls_macros
new file mode 120000
index 0000000..323dd57
--- /dev/null
+++ b/reqd_mask/mls_macros
@@ -0,0 +1 @@
+../private/mls_macros
\ No newline at end of file
diff --git a/reqd_mask/reqd_mask.te b/reqd_mask/reqd_mask.te
new file mode 100644
index 0000000..f77eef4
--- /dev/null
+++ b/reqd_mask/reqd_mask.te
@@ -0,0 +1 @@
+type reqd_mask_type;
diff --git a/reqd_mask/roles b/reqd_mask/roles
new file mode 100644
index 0000000..926cb7a
--- /dev/null
+++ b/reqd_mask/roles
@@ -0,0 +1 @@
+role r types reqd_mask_type;
diff --git a/reqd_mask/roles_decl b/reqd_mask/roles_decl
new file mode 100644
index 0000000..c84fcba
--- /dev/null
+++ b/reqd_mask/roles_decl
@@ -0,0 +1 @@
+role r;
diff --git a/reqd_mask/security_classes b/reqd_mask/security_classes
new file mode 120000
index 0000000..40c1d1d
--- /dev/null
+++ b/reqd_mask/security_classes
@@ -0,0 +1 @@
+../private/security_classes
\ No newline at end of file
diff --git a/reqd_mask/users b/reqd_mask/users
new file mode 100644
index 0000000..51b7b57
--- /dev/null
+++ b/reqd_mask/users
@@ -0,0 +1 @@
+user u roles { r } level s0 range s0 - mls_systemhigh;
diff --git a/tools/Android.mk b/tools/Android.mk
index 023c454..1948b7a 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -46,4 +46,17 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
+###################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := version_policy
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SRC_FILES := version_policy.c
+LOCAL_SHARED_LIBRARIES := libsepol
+LOCAL_CXX_STL := none
+
+include $(BUILD_HOST_EXECUTABLE)
+
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/version_policy.c b/tools/version_policy.c
new file mode 100644
index 0000000..74c9c73
--- /dev/null
+++ b/tools/version_policy.c
@@ -0,0 +1,184 @@
+/*
+ * version_policy.c - Takes the given public platform policy, a private policy
+ * and a version number to produced a combined "versioned" policy file.
+ */
+#include <errno.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <cil/android.h>
+#include <cil/cil.h>
+#include <cil/cil_write_ast.h>
+
+void __attribute__ ((noreturn)) static usage(char *prog) {
+	printf("Usage: %s [OPTION]...\n", prog);
+	printf("\n");
+	printf("Options:\n");
+	printf("  -b, --base=<file>          (req'd) base policy for versioning.\n");
+	printf("  -m, --mapping              generate cil version  mapping from base policy\n");
+	printf("  -n, --number               (req'd) version number to use.\n");
+	printf("  -o, --output=<file>        write cil policy to <file>\n");
+	printf("  -t, --tgt_policy           policy to be versioned according to base policy\n");
+	printf("  -h, --help                 display usage information\n");
+	exit(1);
+}
+
+/*
+ * read_cil_file - Initialize db and parse CIL input file.
+ */
+static int read_cil_file(struct cil_db **db, char *path) {
+	int rc = SEPOL_ERR;
+	FILE *file;
+	struct stat filedata;
+	uint32_t file_size;
+	char *buff = NULL;
+
+	cil_db_init(db);
+	file = fopen(path, "re");
+	if (!file) {
+		fprintf(stderr, "Could not open file: %s\n", path);
+		goto file_err;
+	}
+	rc = stat(path, &filedata);
+	if (rc == -1) {
+		fprintf(stderr, "Could not stat file: %s - %s\n", path, strerror(errno));
+		goto err;
+	}
+	file_size = filedata.st_size;
+	buff = malloc(file_size);
+	if (buff == NULL) {
+		fprintf(stderr, "OOM!\n");
+		rc = SEPOL_ERR;
+		goto err;
+	}
+	rc = fread(buff, file_size, 1, file);
+	if (rc != 1) {
+		fprintf(stderr, "Failure reading file: %s\n", path);
+		rc = SEPOL_ERR;
+		goto err;
+	}
+	fclose(file);
+	file = NULL;
+
+	/* creates parse_tree */
+	rc = cil_add_file(*db, path, buff, file_size);
+	if (rc != SEPOL_OK) {
+		fprintf(stderr, "Failure adding %s to parse tree\n", path);
+		goto err;
+	}
+	free(buff);
+
+	return SEPOL_OK;
+err:
+	free(buff);
+	fclose(file);
+file_err:
+	cil_db_destroy(db);
+	return rc;
+}
+
+int main(int argc, char *argv[])
+{
+	int opt_char;
+	int opt_index = 0;
+	int rc = SEPOL_ERR;
+	bool mapping = false;
+	char *base = NULL;
+	char *tgt_policy = NULL;
+	char *num = NULL;
+	char *output = NULL;
+	struct cil_db *base_db = NULL;
+	struct cil_db *out_db = NULL;
+
+	static struct option long_opts[] = {
+		{"help", no_argument, 0, 'h'},
+		{"base", required_argument, 0, 'b'},
+		{"mapping", no_argument, 0, 'm'},
+		{"number", required_argument, 0, 'n'},
+		{"output", required_argument, 0, 'o'},
+		{"tgt_policy", required_argument, 0, 't'},
+		{0, 0, 0, 0}
+	};
+
+	while (1) {
+		opt_char = getopt_long(argc, argv, "b:mn:o:t:h", long_opts, &opt_index);
+		if (opt_char == -1) {
+			break;
+		}
+		switch (opt_char) {
+		case 'b':
+			base = strdup(optarg);
+			break;
+		case 'm':
+			mapping = true;
+			break;
+		case 'n':
+			num = strdup(optarg);
+			break;
+		case 'o':
+			output = strdup(optarg);
+			break;
+		case 't':
+			tgt_policy = strdup(optarg);
+			break;
+		case 'h':
+			usage(argv[0]);
+		default:
+			fprintf(stderr, "Unsupported option: %s\n", optarg);
+			usage(argv[0]);
+		}
+	}
+	if (optind < argc) {
+		fprintf(stderr, "Unknown arguments supplied\n");
+		usage(argv[0]);
+	}
+	if (num == NULL || base == NULL || (mapping == false && tgt_policy == NULL)) {
+		fprintf(stderr, "Please specify required arguments\n");
+		usage(argv[0]);
+	}
+
+	if (mapping && tgt_policy) {
+		fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n");
+		usage(argv[0]);
+	}
+
+	/* gimme all the details */
+	cil_set_log_level(CIL_INFO);
+
+	/* read platform policy */
+	rc = read_cil_file(&base_db, base);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
+	if (mapping) {
+		rc = cil_android_attrib_mapping(&out_db, base_db, num);
+		if (rc != SEPOL_OK)
+			goto exit;
+	} else {
+		/* read target policy, ready for manipulation */
+		rc = read_cil_file(&out_db, tgt_policy);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+		/* attributize the target policy */
+		rc = cil_android_attributize(out_db, base_db, num);
+		if (rc != SEPOL_OK) {
+			goto exit;
+		}
+	}
+	rc = cil_write_ast(out_db, output);
+	if (rc != SEPOL_OK) {
+		goto exit;
+	}
+
+exit:
+	free(base);
+	free(tgt_policy);
+	free(num);
+	free(output);
+	cil_db_destroy(&base_db);
+	cil_db_destroy(&out_db);
+	return rc;
+}