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
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 at finer granularity.