SELinux plays an important role early in system start-up. Since all of the processes must be labeled with their proper domain, init does some essential actions early in the boot process that keep labeling and policy enforcement in sync.
After the kernel has been loaded during boot, the initial process is assigned the predefined initial SID kernel. Initial SIDs are used for bootstrapping before the policy is loaded.
/sbin/init mounts /proc/, then looks for the selinuxfs file system type. If it is present, that means SELinux is enabled in the kernel.
If init does not find SELinux in the kernel, finds it is disabled via the selinux=0 boot parameter, or if /etc/selinux/config specifies that SELINUX=disabled, boot proceeds with a non-SELinux system.
At the same time, init sets the enforcing status if it is different from the setting in /etc/selinux/config. This happens when a parameter is passed during boot. The default mode is permissive until the policy is loaded, then enforcement is set by the configuration file or by the parameters enforcing=0 or enforcing=1.
If SELinux is present, /selinux/ is mounted.
The kernel checks /selinux/policyvers for the supported policy version. init looks into /etc/selinux/config to see which policy is active, such as the targeted policy, and loads the associated file at $SELINUX_POLICY/policy.<version>.
If the binary policy is not the version supported by the kernel, init attempts to load the policy file if it is a previous version. This provides backward compatibility with older policy versions.
If the local settings in /etc/selinux/targeted/booleans are different from those compiled in the policy, init modifies the policy in memory based on the local settings prior to loading the policy into the kernel.
Now that the policy is loaded, the initial SIDs are mapped to security contexts in the policy, as defined in $SELINUX_SRC/initial_sid_contexts. In the case of the targeted policy, the new domain is user_u:system_r:unconfined_t. The kernel can now begin to get security contexts dynamically from the in-kernel security server.
init then re-executes itself so that it can transition to a different domain, if the policy defines it. For the targeted policy, there is no transition defined and init remains in the unconfined_t domain.
At this point, init continues with its normal boot.
The reason for init to re-execute itself is to accommodate stricter SELinux policy controls. The objective of a re-execution is to transition to a new domain with its own granular rules. The only way a process can gain a domain is during execution, meaning such programs are the only entry points into the domains. For example, if the policy has a specific domain for init such as init_t, there has to be a method to get from the initial SID, such as kernel, to the proper runtime domain for init. Because this transition may need to occur, init is coded to re-execute itself after loading the policy.
This transition with init happens if the rule domain_auto_trans(kernel_t, init_exec_t, <target_domain_t>) is present in the policy. This rule states that an automatic transition occurs on anything executing from the kernel_t domain that executes a file of type init_exec_t. When this execution occurs, the new process is assigned the domain <target_domain_t>, using an actual target domain such as init_t.