Remove execute_no_trans from unconfineddomain.

execute_no_trans controls whether a domain can execve a program
without switching to another domain.  Exclude this permission from
unconfineddomain, add it back to init, init_shell, and recovery for
files in / and /system, and to kernel for files in / (to permit
execution of init prior to setcon).  Prohibit it otherwise for the
kernel domain via neverallow.  This ensures that if a kernel task
attempts to execute a kernel usermodehelper for which no domain transition
is defined, the exec will fail.

Change-Id: Ie7b2349923672dd4f5faf7c068a6e5994fd0e4e3
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/kernel.te b/kernel.te
index 08ccbf5..0844624 100644
--- a/kernel.te
+++ b/kernel.te
@@ -1,6 +1,9 @@
 # Life begins with the kernel.
 type kernel, domain;
 
+# Run /init before we have switched domains.
+allow kernel rootfs:file execute_no_trans;
+
 # setcon to init domain.
 allow kernel self:process setcurrent;
 allow kernel init:process dyntransition;
@@ -38,3 +41,16 @@
 # The initial task starts in the kernel domain (assigned via
 # initial_sid_contexts), but nothing ever transitions to it.
 neverallow domain kernel:process { transition dyntransition };
+
+# The kernel domain is never entered via an exec, nor should it
+# ever execute a program outside the rootfs without changing to another domain.
+# If you encounter an execute_no_trans denial on the kernel domain, then
+# possible causes include:
+# - The program is a kernel usermodehelper.  In this case, define a domain
+#   for the program and domain_auto_trans() to it.
+# - You failed to setcon u:r:init:s0 in your init.rc and thus your init
+#   program was left in the kernel domain and is now trying to execute
+#   some other program.  Fix your init.rc file.
+# - You are running an exploit which switched to the init task credentials
+#   and is then trying to exec a shell or other program.  You lose!
+neverallow kernel { file_type fs_type -rootfs }:file { entrypoint execute_no_trans };