Merge "Change security policy so all apps can read /dev/xt_qtaguid."
diff --git a/Android.mk b/Android.mk
index c023783..e145bb2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,6 +10,13 @@
 MLS_SENS=1
 MLS_CATS=1024
 
+MAC_PERMISSION_FILE=mac_permissions.xml
+
+# Detect if someone tries to union the mac permissions policy file
+$(if $(filter $(MAC_PERMISSION_FILE), $(BOARD_SEPOLICY_UNION)), \
+    $(error Cannot specify $(MAC_PERMISSION_FILE) in BOARD_SEPOLICY_UNION) \
+)
+
 # Quick edge case error detection for BOARD_SEPOLICY_REPLACE.
 # Builds the singular path for each replace file.
 sepolicy_replace_paths :=
@@ -148,15 +155,30 @@
 ##################################
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := mac_permissions.xml
+LOCAL_MODULE := $(MAC_PERMISSION_FILE)
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/security
 
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_SYSTEM)/base_rules.mk
 
-include $(BUILD_PREBUILT)
+# Build keys.conf
+mac_perms_keys.tmp := $(intermediates)/keys.tmp
+$(mac_perms_keys.tmp) : $(call build_policy, keys.conf)
+	@mkdir -p $(dir $@)
+	$(hide) m4 -s $^ > $@
 
+# Build mac_permissions.xml
+$(MAC_PERMISSION_FILE).tmp := $(intermediates)/$(MAC_PERMISSION_FILE).tmp
+$($(MAC_PERMISSION_FILE).tmp) : $(call build_policy, $(MAC_PERMISSION_FILE))
+	@mkdir -p $(dir $@)
+	$(hide) cp $^ $@
+
+$(LOCAL_BUILT_MODULE) : $($(MAC_PERMISSION_FILE).tmp) $(mac_perms_keys.tmp) $(HOST_OUT_EXECUTABLES)/insertkeys.py
+	@mkdir -p $(dir $@)
+	$(HOST_OUT_EXECUTABLES)/insertkeys.py -t $(TARGET_BUILD_VARIANT) -c $(ANDROID_BUILD_TOP) $(mac_perms_keys.tmp) -o $@ $<
+
+$(MAC_PERMISSION_FILE).tmp :=
 ##################################
 
 build_policy :=
diff --git a/README b/README
index 5cba383..085941e 100644
--- a/README
+++ b/README
@@ -56,3 +56,47 @@
         genfs_contexts \
         file_contexts \
         sepolicy.te
+
+SPECIFIC POLICY FILE INFORMATION
+
+mac_permissions.xml:
+  ABOUT:
+    The mac_permissions.xml file is used for controlling the mmac solutions
+    as well as mapping a public base16 signing key with an arbitrary seinfo
+    string. Details of the files contents can be found in a comment at the
+    top of that file. The seinfo string, previously mentioned, is the same string
+    that is referenced in seapp_contexts.
+
+    This file can be replaced through BOARD_SEPOLICY_REPLACE containing the
+    value "mac_permissions.xml", however, appending (UNION) does NOT exist
+    and will cause a build time failure. It is important to note the final
+    processed version of this file is stripped of comments and whitespace.
+    This is to preserve space on the system.img. If one wishes to view it in
+    a more human friendly format, the "tidy" or "xmllint" command will assist
+    you.
+
+  TOOLING:
+    insertkeys.py
+      Is a helper script for mapping arbitrary tags in the signature stanzas of
+      mac_permissions.xml to public keys found in pem files. This script takes
+      a mac_permissions.xml file and configuration file in order to operate.
+      Details of the configuration file (keys.conf) can be found in the subsection
+      keys.conf. This script is also responsible for stipping the comments and
+      whitespace from the xml file.
+
+      keys.conf
+        The keys.conf file is used for controlling the mapping of "tags" found in
+        the mac_permissions.xml signature stanzas with actual public keys found in
+        pem files. The configuration file can be used in BOARD_SEPOLICY_UNION and
+        BOARD_SEPOLICY_REPLACE variables and is processed via m4.
+
+        The script allows for mapping any string contained in TARGET_BUILD_VARIANT
+        with specific path to a pem file. Typically TARGET_BUILD_VARIANT is either
+        user, eng or userdebug. Additionally, one can specify "ALL" to map a path to
+        any string specified in TARGET_BUILD_VARIANT. All tags are matched verbatim
+        and all options are matched lowercase. The options are "tolowered" automatically
+        for the user, it is convention to specify tags and options in all uppercase
+        and tags start with @.
+
+        NOTE: The pem files are base64 encoded and PackageManagerService, mac_permissions.xml
+              and setool all use base16 encodings.
diff --git a/file_contexts b/file_contexts
index 976783f..837ee1d 100644
--- a/file_contexts
+++ b/file_contexts
@@ -1,9 +1,31 @@
 ###########################################
 # Root
-#
-# Nothing required since it is initramfs and implicitly labeled
-# by genfscon rootfs in ocontexts.
-#
+/			u:object_r:rootfs:s0
+
+# Data files
+/adb_keys		u:object_r:rootfs:s0
+/default.prop		u:object_r:rootfs:s0
+/fstab\..*		u:object_r:rootfs:s0
+/init\..*		u:object_r:rootfs:s0
+/res(/.*)?		u:object_r:rootfs:s0
+/ueventd\..*		u:object_r:rootfs:s0
+
+# Executables
+/charger		u:object_r:rootfs:s0
+/init			u:object_r:rootfs:s0
+/sbin(/.*)?		u:object_r:rootfs:s0
+
+# Empty directories
+/lost\+found		u:object_r:rootfs:s0
+/proc			u:object_r:rootfs:s0
+/sys			u:object_r:rootfs:s0
+
+# SELinux policy files
+/file_contexts		u:object_r:rootfs:s0
+/property_contexts	u:object_r:rootfs:s0
+/seapp_contexts		u:object_r:rootfs:s0
+/sepolicy		u:object_r:rootfs:s0
+
 ##########################
 # Devices
 #
diff --git a/keys.conf b/keys.conf
new file mode 100644
index 0000000..387b65a
--- /dev/null
+++ b/keys.conf
@@ -0,0 +1,25 @@
+#
+# Maps an arbitrary tag [TAGNAME] with the string contents found in
+# TARGET_BUILD_VARAINT. Common convention is to start TAGNAME with an @ and
+# name it after the base file name of the pem file.
+#
+# Each tag (section) then allows one to specify any string found in
+# TARGET_BUILD_VARIANT. Typcially this is user, eng, and userdebug. Another
+# option is to use ALL which will match ANY TARGET_BUILD_VARAINT string.
+#
+
+[@PLATFORM]
+ALL : build/target/product/security/platform.x509.pem
+
+[@MEDIA]
+ALL : build/target/product/security/media.x509.pem
+
+[@SHARED]
+ALL : build/target/product/security/shared.x509.pem
+
+# Example of ALL TARGET_BUILD_VARIANTS
+[@RELEASE]
+ENG       : build/target/product/security/testkey.x509.pem
+USER      : build/target/product/security/testkey.x509.pem
+USERDEBUG : build/target/product/security/testkey.x509.pem
+
diff --git a/mac_permissions.xml b/mac_permissions.xml
index 50e9167..55e7bd8 100644
--- a/mac_permissions.xml
+++ b/mac_permissions.xml
@@ -64,13 +64,13 @@
 -->
 
     <!-- Platform dev key with AOSP -->
-    <signer signature="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357" >
+    <signer signature="@PLATFORM" >
       <allow-all />
       <seinfo value="platform" />
     </signer>
 
     <!-- Media dev key in AOSP -->
-    <signer signature="308204a830820390a003020102020900f2b98e6123572c4e300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353233343035375a170d3335303930313233343035375a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100ae250c5a16ef97fc2869ac651b3217cc36ba0e86964168d58a049f40ce85867123a3ffb4f6d949c33cf2da3a05c23eacaa57d803889b1759bcf59e7c6f21890ae25085b7ed56aa626c0989ef9ccd36362ca0e8d1b9603fd4d8328767926ccc090c68b775ae7ff30934cc369ef2855a2667df0c667fd0c7cf5d8eba655806737303bb624726eabaedfb72f07ed7a76ab3cb9a381c4b7dcd809b140d891f00213be401f58d6a06a61eadc3a9c2f1c6567285b09ae09342a66fa421eaf93adf7573a028c331d70601ab3af7cc84033ece7c772a3a5b86b0dbe9d777c3a48aa9801edcee2781589f44d9e4113979600576a99410ba81091259dad98c6c68ff784b8f020103a381fc3081f9301d0603551d0e04160414ca293caa8bc0ed3e542eef4205a2bff2b57e4d753081c90603551d230481c13081be8014ca293caa8bc0ed3e542eef4205a2bff2b57e4d75a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2b98e6123572c4e300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010084de9516d5e4a87217a73da8487048f53373a5f733f390d61bdf3cc9e5251625bfcaa7c3159cae275d172a9ae1e876d5458127ac542f68290dd510c0029d8f51e0ee156b7b7b5acdb394241b8ec78b74e5c42c5cafae156caf5bd199a23a27524da072debbe378464a533630b0e4d0ffb7e08ecb701fadb6379c74467f6e00c6ed888595380792038756007872c8e3007af423a57a2cab3a282869b64c4b7bd5fc187d0a7e2415965d5aae4e07a6df751b4a75e9793c918a612b81cd0b628aee0168dc44e47b10d3593260849d6adf6d727dc24444c221d3f9ecc368cad07999f2b8105bc1f20d38d41066cc1411c257a96ea4349f5746565507e4e8020a1a81" >
+    <signer signature="@MEDIA" >
       <allow-permission name="android.permission.ACCESS_ALL_DOWNLOADS" />
       <allow-permission name="android.permission.ACCESS_CACHE_FILESYSTEM" />
       <allow-permission name="android.permission.ACCESS_DOWNLOAD_MANAGER" />
@@ -92,7 +92,7 @@
     </signer>
 
     <!-- shared dev key in AOSP -->
-    <signer signature="308204a830820390a003020102020900f2a73396bd38767a300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303732333231353735395a170d3335313230393231353735395a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100c8c2dbfd094a2df45c3ff1a32ed21805ec72fc58d017971bd0f6b52c262d70819d191967e158dfd3a2c7f1b3e0e80ce545d79d2848220211eb86f0fd8312d37b420c113750cc94618ae872f4886463bdc4627caa0c0483c86493e3515571170338bfdcc4cd6addd1c0a2f35f5cf24ed3e4043a3e58e2b05e664ccde12bcb67735fd6df1249c369e62542bc0a4729e53917f5c38ffa52d17b73c9c73798ddb18ed481590875547e66bfc5daca4c25a6eb960ed96923709da302ba646cb496b325e86c5c8b2e7a3377b2bbe4c7cf33254291163f689152ac088550c83c508f4bf5adf0aed5a2dca0583f9ab0ad17650db7eea4b23fdb45885547d0feab72183889020103a381fc3081f9301d0603551d0e04160414cb4c7e2cdbb3f0ada98dab79968d172e9dbb1ed13081c90603551d230481c13081be8014cb4c7e2cdbb3f0ada98dab79968d172e9dbb1ed1a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2a73396bd38767a300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010040a8d096997959e917a36c44246b6bac2bae05437ecd89794118f7834720352d1c6f8a39b0869942f4da65981faa2951d33971129ec1921d795671c527d6e249f252829faf5b591310311e2de096500d568ad4114a656dc34a8c6f610453afc1ea7992dba4aa7b3f8543a6e35c0728de77fe97eeac83771fd0ec90f8e4449434ee0b6045783e70c7a2e460249260e003cf7608dc352a4c9ef706def4b26050e978ae2fffd7a3323787014915eb3cc874fcc7a9ae930877c5c8c7d1c2e2a8ee863c89180d1855cedba400e7ba43cccaa7243d397e7c0e8e8e4d7d4f92b6bbead49c0cf018069eddca2e7e2fb4668d89dbbd7950d0cd254180fa1eaafc2a556f84" >
+    <signer signature="@SHARED" >
       <allow-permission name="android.permission.ACCESS_COARSE_LOCATION" />
       <allow-permission name="android.permission.ACCESS_FINE_LOCATION" />
       <allow-permission name="android.permission.ACCESS_NETWORK_STATE" />
@@ -149,7 +149,7 @@
     </signer>
 
     <!-- release dev key in AOSP -->
-    <signer signature="308204a830820390a003020102020900936eacbe07f201df300d06092a864886f70d0101050500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303232393031333334365a170d3335303731373031333334365a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100d6931904dec60b24b1edc762e0d9d8253e3ecd6ceb1de2ff068ca8e8bca8cd6bd3786ea70aa76ce60ebb0f993559ffd93e77a943e7e83d4b64b8e4fea2d3e656f1e267a81bbfb230b578c20443be4c7218b846f5211586f038a14e89c2be387f8ebecf8fcac3da1ee330c9ea93d0a7c3dc4af350220d50080732e0809717ee6a053359e6a694ec2cb3f284a0a466c87a94d83b31093a67372e2f6412c06e6d42f15818dffe0381cc0cd444da6cddc3b82458194801b32564134fbfde98c9287748dbf5676a540d8154c8bbca07b9e247553311c46b9af76fdeeccc8e69e7c8a2d08e782620943f99727d3c04fe72991d99df9bae38a0b2177fa31d5b6afee91f020103a381fc3081f9301d0603551d0e04160414485900563d272c46ae118605a47419ac09ca8c113081c90603551d230481c13081be8014485900563d272c46ae118605a47419ac09ca8c11a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900936eacbe07f201df300c0603551d13040530030101ff300d06092a864886f70d010105050003820101007aaf968ceb50c441055118d0daabaf015b8a765a27a715a2c2b44f221415ffdace03095abfa42df70708726c2069e5c36eddae0400be29452c084bc27eb6a17eac9dbe182c204eb15311f455d824b656dbe4dc2240912d7586fe88951d01a8feb5ae5a4260535df83431052422468c36e22c2a5ef994d61dd7306ae4c9f6951ba3c12f1d1914ddc61f1a62da2df827f603fea5603b2c540dbd7c019c36bab29a4271c117df523cdbc5f3817a49e0efa60cbd7f74177e7a4f193d43f4220772666e4c4d83e1bd5a86087cf34f2dec21e245ca6c2bb016e683638050d2c430eea7c26a1c49d3760a58ab7f1a82cc938b4831384324bd0401fa12163a50570e684d" >
+    <signer signature="@RELEASE" >
       <seinfo value="release" />
       <deny-permission name="android.permission.BRICK" />
       <deny-permission name="android.permission.READ_LOGS" />
diff --git a/mediaserver.te b/mediaserver.te
index 4b299a0..f5274d9 100644
--- a/mediaserver.te
+++ b/mediaserver.te
@@ -2,18 +2,23 @@
 type mediaserver, domain;
 type mediaserver_exec, exec_type, file_type;
 
-init_daemon_domain(mediaserver)
-net_domain(mediaserver)
 typeattribute mediaserver mlstrustedsubject;
-allow mediaserver kernel:system module_request;
+
+net_domain(mediaserver)
+init_daemon_domain(mediaserver)
+unix_socket_connect(mediaserver, property, init)
+
+r_dir_file(mediaserver, sdcard)
+
 binder_use(mediaserver)
 binder_call(mediaserver, binderservicedomain)
 binder_call(mediaserver, appdomain)
 binder_transfer(mediaserver, surfaceflinger)
 binder_service(mediaserver)
+
+allow mediaserver kernel:system module_request;
 allow mediaserver app_data_file:dir search;
 allow mediaserver app_data_file:file r_file_perms;
-r_dir_file(mediaserver, sdcard)
 allow mediaserver sdcard:file write;
 allow mediaserver camera_device:chr_file rw_file_perms;
 allow mediaserver graphics_device:chr_file rw_file_perms;
@@ -21,8 +26,12 @@
 allow mediaserver audio_device:dir r_dir_perms;
 allow mediaserver audio_device:chr_file rw_file_perms;
 allow mediaserver qemu_device:chr_file rw_file_perms;
+allow mediaserver tee_device:chr_file rw_file_perms;
+allow mediaserver audio_prop:property_service set;
+
 # XXX Label with a specific type?
 allow mediaserver sysfs:file rw_file_perms;
+
 # XXX Why?
 allow mediaserver apk_data_file:file { read getattr };
 
@@ -39,7 +48,6 @@
 # Read/[write] to /proc/net/xt_qtaguid/ctrl and /dev/xt_qtaguid
 allow mediaserver qtaguid_proc:file rw_file_perms;
 allow mediaserver qtaguid_device:chr_file r_file_perms;
+
 # Allow abstract socket connection
 allow mediaserver rild:unix_stream_socket connectto;
-
-allow mediaserver tee_device:chr_file rw_file_perms;
diff --git a/property.te b/property.te
index b62004e..ed84c64 100644
--- a/property.te
+++ b/property.te
@@ -7,3 +7,4 @@
 type ctl_default_prop, property_type;
 type ctl_dumpstate_prop, property_type;
 type ctl_rildaemon_prop, property_type;
+type audio_prop, property_type;
diff --git a/property_contexts b/property_contexts
index a08ae80..d86bcb6 100644
--- a/property_contexts
+++ b/property_contexts
@@ -29,6 +29,7 @@
 service.adb.root        u:object_r:shell_prop:s0
 service.adb.tcp.port    u:object_r:shell_prop:s0
 
+persist.audio.          u:object_r:audio_prop:s0
 persist.sys.            u:object_r:system_prop:s0
 persist.service.        u:object_r:system_prop:s0
 persist.security.       u:object_r:system_prop:s0
diff --git a/tools/Android.mk b/tools/Android.mk
index 8d61e25..ab30c3c 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -22,3 +22,14 @@
 LOCAL_STATIC_LIBRARIES := libsepol libselinux
 
 include $(BUILD_HOST_EXECUTABLE)
+
+##################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := insertkeys.py
+LOCAL_SRC_FILES := insertkeys.py
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_PREBUILT)
diff --git a/tools/insertkeys.py b/tools/insertkeys.py
new file mode 100755
index 0000000..e4eeb43
--- /dev/null
+++ b/tools/insertkeys.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+
+from xml.sax import saxutils, handler, make_parser
+from optparse import OptionParser
+import ConfigParser
+import logging
+import base64
+import sys
+import os
+
+__VERSION = (0, 1)
+
+'''
+This tool reads a mac_permissions.xml and replaces keywords in the signature
+clause with keys provided by pem files.
+'''
+
+class GenerateKeys(object):
+    def __init__(self, path):
+        '''
+        Generates an object with Base16 and Base64 encoded versions of the keys
+        found in the supplied pem file argument. PEM files can contain multiple
+        certs, however this seems to be unused in Android as pkg manager grabs
+        the first cert in the APK. This will however support multiple certs in
+        the resulting generation with index[0] being the first cert in the pem
+        file.
+        '''
+
+        self._base64Key = list()
+        self._base16Key = list()
+
+        if not os.path.isfile(path):
+            sys.exit("Path " + path + " does not exist or is not a file!")
+
+        pkFile = open(path, 'rb').readlines()
+        base64Key = ""
+        inCert = False
+        for line in pkFile:
+            if line.startswith("-"):
+                inCert = not inCert
+                continue
+
+            base64Key += line.strip()
+
+        # Base 64 includes uppercase. DO NOT tolower()
+        self._base64Key.append(base64Key)
+
+        # Pkgmanager and setool see hex strings with lowercase, lets be consistent.
+        self._base16Key.append(base64.b16encode(base64.b64decode(base64Key)).lower())
+
+    def __len__(self):
+        return len(self._base16Key)
+
+    def __str__(self):
+        return str(self.getBase16Keys())
+
+    def getBase16Keys(self):
+        return self._base16Key
+
+    def getBase64Keys(self):
+        return self._base64Key
+
+class ParseConfig(ConfigParser.ConfigParser):
+
+    # This must be lowercase
+    OPTION_WILDCARD_TAG = "all"
+
+    def generateKeyMap(self, target_build_variant):
+
+        keyMap = dict()
+
+        for tag in self.sections():
+
+            options = self.options(tag)
+
+            for option in options:
+
+                # Only generate the key map for debug or release,
+                # not both!
+                if option != target_build_variant and \
+                option != ParseConfig.OPTION_WILDCARD_TAG:
+                    logging.info("Skipping " + tag + " : " + option +
+                        " because target build variant is set to " +
+                        str(target_build_variant))
+                    continue
+
+                if tag in keyMap:
+                    sys.exit("Duplicate tag detected " + tag)
+
+                path = self.get(tag, option)
+
+                keyMap[tag] = GenerateKeys(path)
+
+                # Multiple certificates may exist in
+                # the pem file. GenerateKeys supports
+                # this however, the mac_permissions.xml
+                # as well as PMS do not.
+                assert len(keyMap[tag]) == 1
+
+        return keyMap
+
+class ReplaceTags(handler.ContentHandler):
+
+    DEFAULT_TAG = "default"
+    PACKAGE_TAG = "package"
+    POLICY_TAG = "policy"
+    SIGNER_TAG = "signer"
+    SIGNATURE_TAG = "signature"
+
+    TAGS_WITH_CHILDREN = [ DEFAULT_TAG, PACKAGE_TAG, POLICY_TAG, SIGNER_TAG ]
+
+    XML_ENCODING_TAG = '<?xml version="1.0" encoding="iso-8859-1"?>'
+
+    def __init__(self, keyMap, out=sys.stdout):
+
+        handler.ContentHandler.__init__(self)
+        self._keyMap = keyMap
+        self._out = out
+
+    def startDocument(self):
+        self._out.write(ReplaceTags.XML_ENCODING_TAG)
+        self._out.write("<!-- AUTOGENERATED FILE DO NOT MODIFY -->")
+
+    def startElement(self, tag, attrs):
+
+        self._out.write('<' + tag)
+
+        for (name, value) in attrs.items():
+
+            if name == ReplaceTags.SIGNATURE_TAG and value in self._keyMap:
+                for key in self._keyMap[value].getBase16Keys():
+                    logging.info("Replacing " + name + " " + value + " with " + key)
+                    self._out.write(' %s="%s"' % (name, saxutils.escape(key)))
+            else:
+                self._out.write(' %s="%s"' % (name, saxutils.escape(value)))
+
+        if tag in ReplaceTags.TAGS_WITH_CHILDREN:
+            self._out.write('>')
+        else:
+            self._out.write('/>')
+
+    def endElement(self, tag):
+        if tag in ReplaceTags.TAGS_WITH_CHILDREN:
+            self._out.write('</%s>' % tag)
+
+    def characters(self, content):
+        if not content.isspace():
+            self._out.write(saxutils.escape(content))
+
+    def ignorableWhitespace(self, content):
+        pass
+
+    def processingInstruction(self, target, data):
+        self._out.write('<?%s %s?>' % (target, data))
+
+if __name__ == "__main__":
+
+    # Intentional double space to line up equls signs and opening " for
+    # readability.
+    usage  = "usage: %prog [options] CONFIG_FILE MAC_PERMISSIONS_FILE\n"
+    usage += "This tool allows one to configure an automatic inclusion "
+    usage += "of signing keys into the mac_permision.xml file from the "
+    usage += "pem files."
+
+    version = "%prog " + str(__VERSION)
+
+    parser = OptionParser(usage=usage, version=version)
+
+    parser.add_option("-v", "--verbose",
+                      action="store_true", dest="verbose", default=False,
+                      help="Print internal operations to stdout")
+
+    parser.add_option("-o", "--output", default="stdout", dest="output_file",
+                      metavar="FILE", help="Specify an output file, default is stdout")
+
+    parser.add_option("-c", "--cwd", default=os.getcwd(), dest="root",
+                      metavar="DIR", help="Specify a root (CWD) directory to run this from, it" \
+                                          "chdirs' AFTER loading the config file")
+
+    parser.add_option("-t", "--target-build-variant", default="eng", dest="target_build_variant",
+                      help="Specify the TARGET_BUILD_VARIANT, defaults to eng")
+
+
+    (options, args) = parser.parse_args()
+
+    if len(args) != 2:
+        parser.error("Must specify a config file (keys.conf) AND mac_permissions.xml file!")
+
+    logging.basicConfig(level=logging.INFO if options.verbose == True else logging.WARN)
+
+    # Read the config file
+    config = ParseConfig()
+    config.read(args[0])
+
+    os.chdir(options.root)
+
+    output_file = sys.stdout if options.output_file == "stdout" else open(options.output_file, "w")
+    logging.info("Setting output file to: " + options.output_file)
+
+    # Generate the key list
+    key_map = config.generateKeyMap(options.target_build_variant.lower())
+    logging.info("Generate key map:")
+    for k in key_map:
+        logging.info(k + " : " + str(key_map[k]))
+    # Generate the XML file with markup replaced with keys
+    parser = make_parser()
+    parser.setContentHandler(ReplaceTags(key_map, output_file))
+    parser.parse(args[1])
diff --git a/zygote.te b/zygote.te
index 3350ce3..743af36 100644
--- a/zygote.te
+++ b/zygote.te
@@ -6,6 +6,8 @@
 typeattribute zygote mlstrustedsubject;
 # Override DAC on files and switch uid/gid.
 allow zygote self:capability { dac_override setgid setuid };
+# Drop capabilities from bounding set.
+allow zygote self:capability setpcap;
 # Switch SELinux context to app domains.
 allow zygote system:process dyntransition;
 allow zygote appdomain:process dyntransition;