Task Hook Functions

The SELinux task hook function implementations manage the security fields of task_struct structures and perform access control for task operations. This section describes these hooks and their helper functions.

Managing Task Security Fields

Task Security Structure

The task_security_struct structure contains security information for tasks. This structure is defined as follows:

struct task_security_struct {
        unsigned long magic;
        struct task_struct *task;
        struct list_head list;
        security_id_t osid;
        security_id_t sid;
        security_id_t in_sid[2];
        security_id_t out_sid[2];
        avc_entry_ref_t avcr;
};

Table 1. task_security_struct

FieldDescription
magicModule id for the SELinux module.
taskBack pointer to the associated task_struct structure.
listPointer used to maintain the list of allocated task security structures.
osidSID prior to the last execve.
sidSID for the task.
in_sid[2]Input SIDs used by SELinux system calls.
out_sid[2]Output SIDs returned by SELinux system calls.
avcrAVC entry reference.

task_alloc_security and task_free_security

The task_alloc_security and task_free_security helper functions are the primitive allocation functions for task security structures. The selinux_task_alloc_security hook function calls task_alloc_security for the new task and then copies the SID fields from the current task into the new task. The selinux_task_free_security hook function simply calls the corresponding helper function.

task_precondition

This helper function is the precondition function for task security structures. This function ensures that the task security structure is allocated and initialized prior to use. If the task security structure is not already allocated, then the task was created prior to the loading of the SELinux module. In this case, this helper function attempts to retroactively determine the SID for the task.

If the task has no parent task, then this function assigns the kernel initial SID to the task. Otherwise, the security structure of the parent task is obtained and used to provide default values for the child task's security structure. The security structure for the inode that represents the task's executable is then obtained, and the SID of the task is computed based on the SID of the parent task and the SID of the inode using the security_transition_sid interface.

This parallels the computation that would occur normally if the parent task had forked the child and then the child had executed the program while running SELinux. However, there are several possible reasons why this computation might yield a different SID than the SID that would have been used if the SELinux module had been running when the child task was created. For example, the original parent task may have died or undergone a change in SID since creating the child. Additionally, if SELinux had been running at an earlier point, then the child task or one of its ancestors might have used one of the new system calls to explicitly set the SID, e.g. to set the user identity and role upon login.

selinux_task_kmod_set_label

This hook function is called by the kernel exec_usermodehelper function to set the security attributes for the kernel task running user-mode helper programs, such as modprobe. This is used for operations such as automatic kernel module loading and hotplug support. This hook function first calls the secondary security module to support Linux capabilities. It then sets the SID of the task to the kmod initial SID.

selinux_task_post_setuid

This hook function is called after a setuid operation has successfully completed. Since the SELinux module does not use the Linux identity attributes, this hook function does not perform any SELinux processing. However, it does call the secondary security module to support Linux capabilities.

Controlling Task Operations

Helper Functions for Checking Task Permissions

Several helper functions are provided for performing task permission checks. These functions and their permission checks are summarized in Table 2. The task_has_perm function checks whether a task has a particular permission to another task. The task_has_capability function checks whether a task has permission to use a particular Linux capability. The task_has_system function checks whether a task has one of the permissions in the system security class. This security class is used for permissions that control system operations when there is no existing capability check or the capability check is too coarse-grained. The task_has_security function checks whether a task has permission to use one of the security server system calls.

Table 2. Task Helper Function Permission Checks

FunctionSourceTargetPermission(s)
task_has_permSourceTaskTargetTaskProcessPermission
task_has_capabilityTaskTaskCapabilityPermission
task_has_systemTaskKernelSystemPermission
task_has_securityTaskSecuritySecurityPermission

Except for task_has_perm, these permission checks are simply based on a single task, so the target SID is unnecessary. In the case of task_has_capability, the task's SID is passed for both the source and target SIDs. For task_has_system and task_has_security, a distinct initial SID is used for the target SID.

Hook Functions for Controlling Task Operations

The task hook functions that perform access control and their permission checks are summarized in Table 3. These functions call the task_has_perm helper function.

Table 3. Task Hook Function Permission Checks

HookSourceTargetPermission(s)
selinux_task_createCurrentCurrentfork
selinux_task_setpgidCurrentTargetTasksetpgid
selinux_task_getpgidCurrentTargetTaskgetpgid
selinux_task_getsidCurrentTargetTaskgetsession
selinux_task_getschedulerCurrentTargetTaskgetsched

selinux_task_setscheduler
selinux_task_setnice

CurrentTargetTasksetsched
selinux_task_killCurrentTargetTask

sigchld
sigkill
sigstop
signal

selinux_task_waitChildTaskCurrent

sigchld
sigkill
sigstop
signal

Only two of these hook functions require further explanation. The selinux_task_kill hook function checks a permission between the current task and the target task based on the signal being sent. The selinux_task_wait checks a permission between the child task and the current task based on the exit signal set for the child task. This allows control over the ability of a process to reap a child process of a different SID. In both hooks, the SIGKILL and SIGSTOP signals have their own distinct permissions because neither of these two signals can be blocked. The SIGCHLD signal has its own distinct permission because it is commonly sent from child processes to parent processes. For all other signals, the generic signal permission is used.

Several of the task hook functions for controlling operations are not used by the SELinux security module. These hook functions are:

  • selinux_task_setuid

  • selinux_task_setgid

  • selinux_task_setgroups

  • selinux_task_setrlimit

  • selinux_task_prctl

Since SELinux does not depend on the Linux identity attributes, and since these operations can only affect the current process, SELinux does not need to control these operations. Privileged aspects of these operations are already controlled via the selinux_capable hook function. However, it may be desirable in the future to add SELinux permissions to control these operations, e.g. to confine Linux identity changes or to provide policy control over resource limits.