From d99e6d5fa135882bb51878a3c68ed3a2aebe7d04 Mon Sep 17 00:00:00 2001
From: Stephen Smalley <sds@tycho.nsa.gov>
Date: Mon, 2 Dec 2013 14:18:11 -0500
Subject: [PATCH] Restrict the ability to set SELinux enforcing mode to init.

Also make su and shell permissive in non-user builds to allow
use of setenforce without violating the neverallow rule.

Change-Id: Ie76ee04e90d5a76dfaa5f56e9e3eb7e283328a3f
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
---
 Android.mk    | 2 ++
 domain.te     | 4 ++--
 init.te       | 2 +-
 shell.te      | 3 +++
 shell_user.te | 8 ++++++++
 su.te         | 3 +++
 te_macros     | 8 ++------
 unconfined.te | 2 +-
 8 files changed, 22 insertions(+), 10 deletions(-)
 create mode 100644 shell_user.te

diff --git a/Android.mk b/Android.mk
index 0121b6e57..a3cd38541 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 55a7b8162..77409e8e3 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 6f2f47fab..93098e175 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 8b51003df..032f70ffc 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 000000000..8b51003df
--- /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 b68536c3a..dda77080b 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 7be9d5900..3ccb86fea 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 35db54f75..f6899c27a 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 *;
-- 
GitLab