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 SIDkernel. 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.