diff --git a/Android.mk b/Android.mk
index 0121b6e57328393d22fa33f92da36bc76d460fd7..a3cd385416e2f6e5738b908cd12231cc9f94c4d3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,8 +11,10 @@ MLS_SENS=1
 MLS_CATS=1024
 
 ifeq ($(TARGET_BUILD_VARIANT),user)
+	BOARD_SEPOLICY_IGNORE+=external/sepolicy/shell.te
 	BOARD_SEPOLICY_IGNORE+=external/sepolicy/su.te
 else
+	BOARD_SEPOLICY_IGNORE+=external/sepolicy/shell_user.te
 	BOARD_SEPOLICY_IGNORE+=external/sepolicy/su_user.te
 endif
 
diff --git a/domain.te b/domain.te
index 55a7b8162a6af5f4021deab8cb79308a018cd891..77409e8e33861637cfda17bd94d6a7eedbc37cf2 100644
--- a/domain.te
+++ b/domain.te
@@ -131,8 +131,8 @@ neverallow { domain -relabeltodomain } *:dir_file_class_set relabelto;
 ### neverallow rules
 ###
 
-# Only init should be able to load SELinux policies
-neverallow { domain -init } kernel:security load_policy;
+# Only init should be able to load SELinux policies and set enforcing mode.
+neverallow { domain -init } kernel:security { load_policy setenforce };
 
 # Only init, ueventd and system_server should be able to access HW RNG
 neverallow { domain -init -system_server -ueventd -unconfineddomain } hw_random_device:chr_file *;
diff --git a/init.te b/init.te
index 6f2f47fabd54501ba344f7b36831229e06f03b96..93098e1757ff539b82beaf4f1a0e461e7c4e7bb4 100644
--- a/init.te
+++ b/init.te
@@ -8,4 +8,4 @@ relabelto_domain(init)
 allow init unlabeled:filesystem mount;
 
 allow init {fs_type dev_type file_type}:dir_file_class_set relabelto;
-allow init kernel:security load_policy;
+allow init kernel:security { load_policy setenforce };
diff --git a/shell.te b/shell.te
index 8b51003dfe90c2867af25cdcfdbb03ddf4ee525a..032f70ffc10a26e5ec5cde3208966e94202f906a 100644
--- a/shell.te
+++ b/shell.te
@@ -6,3 +6,6 @@ unconfined_domain(shell)
 # Run app_process.
 # XXX Split into its own domain?
 app_domain(shell)
+
+# shell is also permissive to permit setenforce.
+permissive shell;
diff --git a/shell_user.te b/shell_user.te
new file mode 100644
index 0000000000000000000000000000000000000000..8b51003dfe90c2867af25cdcfdbb03ddf4ee525a
--- /dev/null
+++ b/shell_user.te
@@ -0,0 +1,8 @@
+# Domain for shell processes spawned by ADB
+type shell, domain;
+type shell_exec, exec_type, file_type;
+unconfined_domain(shell)
+
+# Run app_process.
+# XXX Split into its own domain?
+app_domain(shell)
diff --git a/su.te b/su.te
index b68536c3aa1998e82ceb22901ba1e87ea720cfd0..dda77080bf360c577cbf00a52cf25593e52e85bd 100644
--- a/su.te
+++ b/su.te
@@ -4,3 +4,6 @@ domain_auto_trans(shell, su_exec, su)
 
 # su is unconfined.
 unconfined_domain(su)
+
+# su is also permissive to permit setenforce.
+permissive su;
diff --git a/te_macros b/te_macros
index 7be9d5900249dcd836a35c7a2aff233e3c2f0115..3ccb86feac79065b6b193b612b76bd2457841ab4 100644
--- a/te_macros
+++ b/te_macros
@@ -250,13 +250,9 @@ allow $1 rootfs:file r_file_perms;
 
 #####################################
 # selinux_manage_policy(domain)
-# Ability to manage policy files,
-# trigger runtime reload, change
-# enforcing mode, manipulate booleans
-# and access kernel logs.
+# Ability to manage policy files and
+# trigger runtime reload.
 define(`selinux_manage_policy', `
-selinux_setenforce($1)
-selinux_setbool($1)
 security_access_policy($1)
 unix_socket_connect($1, property, init)
 allow $1 security_file:dir create_dir_perms;
diff --git a/unconfined.te b/unconfined.te
index 35db54f75b5e58f359db90b3dd473f75d57e8b05..f6899c27a0a039758c8819d7526eb6bb69090edf 100644
--- a/unconfined.te
+++ b/unconfined.te
@@ -17,7 +17,7 @@
 ######################################################
 
 allow unconfineddomain self:capability_class_set *;
-allow unconfineddomain kernel:security ~load_policy;
+allow unconfineddomain kernel:security ~{ load_policy setenforce };
 allow unconfineddomain kernel:system *;
 allow unconfineddomain self:memprotect *;
 allow unconfineddomain domain:process *;