Pages

Wednesday, June 13, 2012

Overview of the LSM and SELinux internal structure and workings

Major areas covered are:

  • How the LSM and SELinux modules work together.
  • The boot sequences that are relevant to SELinux. 

LSM Module:

The LSM is the Linux security framework that allows 3rd party access control mechanisms to be linked into the GNU / Linux kernel. Currently there are two 3rd party services that utilize the LSM: SELinux and SMACK (Simplified Mandatory Access Control Kernel) that both provide mandatory access control services.

 The basic idea behind the LSM is to: 

  • Insert security function calls (or hooks) and security data structures in the various kernel services to allow access control to be applied.
  • Allow registration and initialization services for the 3rd party security modules.  
  • Allow process security attributes to be available to user-space services by extending the /proc filesystem 
  • with a security namespace.
  • Support filesystems that use extended attributes.
  • Consolidate the Linux capabilities into an optional module. 
Note: LSM does not provide any security services itself, only the hooks and structures for supporting 3rd party modules. If no 3rd party modules is loaded, the capabilities module become the default module thus allowing standard DAC.

Kernel services for which LSM has inserted hooks and structures to allow access control managed by 3rd party module:

Program Execution                        Filesystem Operations                       Inode Operations

File operations                                 Task operations                                     Netlink messeging
Unix domain networking                   Socket operations                                 XFRM operations
Key management operations            IPC operations                                      Memory Segments
Seamaphores                                  Capability                                              Sysctl
Syslogs                                           Audit

Major kernel source that form LSM: 

capabilty.c
commoncap.c
device_cgroup.c
inode.c
root_plug.c
security.c

SELinux Module:

Diagrams briefly explains how various kernel modules fit together :
 

 

SELinux Boot Process:

 

The Role of Policy in the Boot Process

SELinux plays an important role during the early stages of system start-up. Because all processes must be labeled with their correct domain, init performs some essential operations early in the boot process to maintain synchronization between labeling and policy enforcement.
  1. After the kernel has been loaded during the boot process, the initial process is assigned the predefined initial SELinux ID (initial SID) kernel. Initial SIDs are used for bootstrapping before the policy is loaded.
  2. /sbin/init mounts /proc/, and then searches for the selinuxfs file system type. If it is present, that means SELinux is enabled in the kernel.
  3. If init does not find SELinux in the kernel, or if it is disabled via the selinux=0 boot parameter, or if /etc/selinux/config specifies that SELINUX=disabled, the boot process 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 the boot process. 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.
  4. If SELinux is present, /selinux/ is mounted.
  5. The kernel checks /selinux/policyvers for the supported policy version. init instpects /etc/selinux/config to determine which policy is active, such as the targeted policy, and loads the associated file at $SELINUX_POLICY/policy..
    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.
  6. By this stage of the process, the policy is fully loaded into the kernel. The initial SIDs are then mapped to security contexts in the policy. In the case of the targeted policy, the new domain is user_u:system_r:unconfined_t. The kernel can now begin to retrieve security contexts dynamically from the in-kernel security server.
  7. 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.
  8. At this point, init continues with its normal boot process.




Start Kernel Boot Process
|
./init/main.c start_kernel()
|
Load the initial RAM Disk (this is a temporary root filesystem). The source
code for this and nash(8) is in the mkinitrd source code.
|
Kernel calls security_init() to initialise the LSM security framework.
For SELinux this results in a call to selinux_init() that is in hooks.c
|
Set the kernel context to the initial SID value "1" taken from
include/flask.h (SECINITSID_KERNEL)
|
The AVC is initialised by a call to avc_init()
|
Other areas of SELinux get initialised such as the
selinuxfs (/selinux) pseudo filesystem and netlink with their
objects set with the initial SIDs from flask.h
|
/sbin/nash is run by the kernel.
|
/sbin/nash initialises services such as drivers, loads the root filesystem
read-only and loads the SELinux policy using the loadPolicyCommand.
This function will check various directories, then call the SELinux API
the selinux_init_load_policy function to load the policy.
|
Loading the policy will now complete the SELinux initialisation
with a call to selinux_complete_init() in hooks.c.
SELinux will now start enforcing policy or allow permissive access
depending on the value set in /etc/selinux/config SELINUX=
|
The kernel is now loaded, the RAM disk removed, SELinux is
initialised, the policy loaded and /sbin/init is running
with the root filesystem in read only mode.
|
End Kernel Load and Initialisation
|
/etc/rc.d/sysinit is run by init that will:
|
mount /proc and sysfs filesystems
|
Check that the selinuxfs (/selinux) pseudo filesystem
is present and whether the current process is labeled kernel_t
|
If the current SELinux state can be read (/selinux/enforce),
then set to value. If cannot read, set to "1".
|
Run restorecon -R on /dev if needed.
|
Kill off /sbin/nash if it is still running.
|
Run restorecon on /dev/pts if needed.
|
Set contexts on the files in /etc/rwtab and /etc/statetab
by running restorecon -R path.
|
Check if relabeling required:
if ./autorelabel file + AUTORELABEL=0 (in /etc/selinux/config):
then drop to shell for manual relabel, or
if only ./autorelabel file, then run fixfiles -F restore.
|
remove ./autorelabel file.
|
If /sbin/init has changed context after the relabel,
then ensure a reboot. ELSE carry on.
|
/etc/rc.d/sysinit will do other initialisation tasks, then exit.
|
Note: Some SELinux notes state that /sbin/init is re-exec"ed
to allow it to run in the correct context. Could not find where this
happened as policy seems to be active before init daemon is run ??
|
Initialisation Complete


References :

                         http://selinuxproject.org/page/NB_LSM
                         http://www.nsa.gov/research/_files/publications/implementing_selinux.pdf




No comments: