The SELinux file hook functions manage the security fields of
file
structures and perform access control
for file operations. Each file
structure
contains state such as the file offset and file flags for an open
file. Since file descriptors may be inherited across
execve
calls and may be transferred through IPC,
they can potentially be shared among processes with different security
attributes, so it is desirable to separately label these structures
and control the use of them. Additionally, it is necessary to save
task security information in these structures for SIGIO
signals.
The file_security_struct
structure contains
security information for file objects. This structure is defined as
follows:
struct file_security_struct { unsigned long magic; struct file *file; struct list_head list; security_id_t sid; security_id_t fown_sid; avc_entry_ref_t avcr; avc_entry_ref_t inode_avcr; };
Table 20. file_security_struct
Field | Description |
---|---|
magic | Module id for the SELinux module. |
file | Back pointer to the associated file .
|
list | Pointer used to maintain the list of allocated file security structures. |
sid | SID of the open file descriptor. |
fown_sid | SID of the file owner; used for SIGIO
events.
|
avcr | AVC entry reference for the file. |
inode_avcr | AVC entry reference for the associated inode. |
The file_alloc_security
and
file_free_security
helper functions are the
primitive allocation functions for file security structures. In
addition to the general security field management,
file_alloc_security
tries to associate the file
with the SID of the current task. If the security structure of the
current task is not already set, the file is associated with the
unlabeled SID. Callers of this function should first call
task_precondition
on the current task if
possible. The file_free_security
simply releases
all resources.
The selinux_file_alloc_security
calls the
task_precondition
function to ensure that the SID
of the current task is set and then calls the helper
function. The selinux_file_free_security
hook
functions merely calls the helper function.
The file_precondition
helper function ensures
that the file security structure is allocated and initialized prior to
use. This function calls task_precondition
on the current task and then calls file_alloc_security
.
This hook function is called to save security information about the
current task in the file security structure for later use by the
selinux_file_send_sigiotask
hook. One example of
where this hook is called is the fcntl
call for
the F_SETOWN
command. This hook saves the SID of
the current task in the fown_sid
field of
the file security structure.
This helper function checks whether a task can use an open file descriptor to
access a file in a given way. It takes the task, the file, and the
requested file permissions as parameters. This function first calls
the AVC to check use
permission between the task
and the file descriptor. If this permission is granted, then this
function also checks the requested permissions to the file using the
dentry_has_perm
helper function. In some cases
(e.g. lseek), this helper function is called with no requested file
permissions in order to simply check the ability to use the
descriptor. In these cases, the latter check is omitted.
This hook function is called by operations such as
read
, write
, and
sendfile
to revalidate permissions on use to
support privilege bracketing or policy changes. It takes the file and
permission mask as parameters. If the O_APPEND
flag is set in the file flags, then this hook function first sets the
MAY_APPEND
flag in permission mask. This
function then converts the permission mask to an access vector using
the file_mask_to_av
function, and calls
file_has_perm
with the appropriate parameters.
This hook function is called by the lseek
and llseek
system calls to control access
to the file offset. It calls file_has_perm
with no requested file permissions to simply check access to the
file descriptor.
This hook function is called by the ioctl
system
call. It calls file_has_perm
with a requested
file permission based on the command argument. For some commands, no
file permission is specified so only the use
permission is checked. The generic ioctl
file permission is used for commands that are not specifically handled.
Table 21 shows the permission checks performed for each
command.
Table 21. I/O Control Permission Checks
Command | Source | Target | Permission(s) | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
| Current |
|
| |||||||||
| Current |
|
| |||||||||
| Current | FileDescriptor | use | |||||||||
Other | Current |
|
|
This hook function is called by mmap
to check
permission when mapping a file. At present, if anonymous memory is
being mapped, i.e. the file parameter is NULL
, no checks are
performed. However, this may be changed later to ensure that execute
access to anonymous memory can be controlled. If a file is being
mapped, then file_has_perm
is called with a
set of permissions based on the flags and protection parameters.
Since read access is always possible with file mapping, the
read
permission is always required. The
write
permission is only checked if the mapping
is shared and PROT_WRITE
was requested. The
execute
permission is only checked if
PROT_EXEC
was requested. However, on some
architectures, read access to memory is sufficient to execute code
from it, so the ability to strictly control code execution is
limited on such architectures.
It should be noted that the protection on a mapping may subsequently become invalid due to a file relabel or a change in the security policy. Hence, support for efficiently locating and invalidating the appropriate mappings upon such changes is needed to support full revocation. This support has not yet been implemented for the SELinux security module.
This hook function is called by the mprotect
call
to check the requested new protection for an existing mapping. This
hook simply calls selinux_file_mmap
with the
file, new protection value, and the existing flags for the mapping.
This hook function is called by the flock
system
call. It calls file_has_perm
with the
lock
permission.
This hook function is called by the fcntl
system
call. It calls file_has_perm
with a requested
file permission based on the command parameter.
The basic permission checks performed for each command are shown in
Table 22.
Table 22. File Control Permission Checks
Command | Source | Target | Permission(s) | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Current | FileDescriptor | use | ||||||||||
| Current |
|
|
In addition to these basic checks, the write
permission is checked if the F_SETFL
command is
used to clear the O_APPEND
flag. This ensures
that a process that only has append
permission to
the file cannot subsequently obtain full write access after opening
the file.
This hook function is called to check whether a signal generated by an
event on a file descriptor can be sent to a task. This function is
always called from interrupt. It is passed the target task, a file
owner structure and several other parameters that are unused by
SELinux. Since the file owner structure is embedded in a file
structure, the file structure and its security field can be extracted
by the hook function. The hook function calls the AVC to check the
appropriate signal permission between the
fown_sid
in the file security structure and
the target task SID.
This hook function is called to check whether the current task can
receive an open file descriptor that was sent via socket IPC. This
function calls the file_to_av
function to convert
the file flags and mode to an access vector and then calls
file_has_perm
to check that the receiving task
has these permissions to the file. If this hook returns an error,
then the kernel will cease processing the message and will pass
a truncated message to the receiving task.