Implementing SELinux as a Linux Security Module | ||
---|---|---|
<<< Previous | Next >>> |
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.
The task_security_struct
structure contains
security information for tasks. This structure is defined as follows:
struct task_security_struct { struct task_struct *task; u32 osid; u32 sid; u32 exec_sid; u32 create_sid; u32 ptrace_sid; }; |
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.
This hook function is called by the kernel
reparent_to_init function to set the security
attributes for a kernel task. This hook function first calls the secondary
security module to support Linux capabilities. It then sets the SID
of the task to the kernel
initial SID.
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.
This hook function is called by the procfs pseudo filesystem to set the security state for the /proc/pid inodes associated with a task. This function sets the inode SID from the task SID and marks the inode security structure as initialized.
This hook function is called by the procfs pseudo filesystem to get a
process security attribute value from the security module upon an
attempt to read a node under the /proc/pid/attr directory. The hook
function begins by checking getattr
permission if
the target task differs from the current task. It then extracts the
appropriate SID from the task security structure. If the
corresponding SID has not been set (e.g. if no explicit exec SID has
been set and the task is using the default policy behavior), then the
hook returns a zero length. Otherwise, the hook function calls
security_sid_to_context to obtain the security
context associated with the SID, copies the context to the provided
kernel buffer (if it is large enough), and returns its length.
This hook function is called by the procfs pseudo filesystem to set a process security attribute value from the security module upon an attempt to write a node under the /proc/pid/attr directory. The hook function begins by checking whether the target task differs from the current task, returning an error in that case to prevent setting of a task's security attributes by another task. The function then applies a permission check between the current task and the target task (always a self relationship due to the prior restriction) based on the particular attribute being set. If a context was written to the node (as opposed to writing a zero length buffer to reset an exec or fscreate SID to the default policy behavior), then the function calls security_context_to_sid to convert it to a SID.
If the attribute is the exec or fscreate context, then the function proceeds to set the corresponding SID in the task security structure. For these attributes, further permission checks based on the specified security context are not performed until the execve or file creation operation occurs, at which point that operation may fail due to a lack of permission. This is partly a legacy of the original API, where extended system calls specified the SID for the operation as part of the operation call rather than separately setting a process attribute in advance. While it would be possible to duplicate some of this checking within the selinux_setprocattr hook function (e.g. process transition permission check), the hook function lacks the full context of the execve or file creation operation, e.g. the entrypoint program for execve and the parent directory, filesystem, and specific file type for file creation.
If the attribute is the current context (i.e. a dynamic context
transition), then the hook function verifies that there are no other
threads in the process, checks dyntransition
permission between the old and new task SIDs, and if the process is
being traced, checks ptrace
permission between
the tracer SID and the new SID. If all checks pass, then the task SID
is set to the new value.
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 selinuxfs APIs.
Table 2. Task Helper Function Permission Checks
Function | Source | Target | Permission(s) |
---|---|---|---|
task_has_perm | SourceTask | TargetTask | ProcessPermission |
task_has_capability | Task | Task | CapabilityPermission |
task_has_system | Task | Kernel | SystemPermission |
task_has_security | Task | Security | SecurityPermission |
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.
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
Hook | Source | Target | Permission(s) | |||||
---|---|---|---|---|---|---|---|---|
selinux_task_create | Current | Current | fork | |||||
selinux_task_setpgid | Current | TargetTask | setpgid | |||||
selinux_task_getpgid | Current | TargetTask | getpgid | |||||
selinux_task_getsid | Current | TargetTask | getsession | |||||
selinux_task_getscheduler | Current | TargetTask | getsched | |||||
| Current | TargetTask | setsched | |||||
selinux_task_kill | Current | TargetTask |
| |||||
selinux_task_wait | ChildTask | Current |
| |||||
selinux_task_setrlimit | Current | Current | setrlimit | |||||
selinux_ptrace | Parent | Child | ptrace |
Only three 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.
The signull
permission is checked if a 0 signal
is passed to kill, as this merely represents an existence test, not an
actual signal delivery. For all other signals, the generic
signal
permission is used.
The selinux_task_rlimit hook checks
setrlimit
permission if a hard limit is being
changed so that the hard limit can later be used as a safe reset point
for the soft limit upon context transitions. See the section on
selinux_bprm_apply_creds for further discussion
of the resource limit inheritance control.
In addition to checking ptrace permission, the selinux_ptrace hook also sets the tracer SID in the child task's security structure for later use by selinux_bprm_apply_creds and selinux_setprocattr. See the Section called selinux_bprm_apply_creds and the Section called selinux_setprocattr for further discussion.
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_prctl
<<< Previous | Home | Next >>> |
Helper Functions for Hook Functions | Program Loading Hook Functions |