next up previous contents
Next: API extensions Up: Design Previous: Permissions   Contents


Control Requirements


Table 4: Process Management Control Requirements.
  CONTROL REQUIREMENT(S)
CALL(S) Class Permission Source SID Target SID
execve Dir search Current Path
  File execute Current File
  Process transition Current New
  Process entrypoint New File
  Process execute New File
  Process ptrace Parent New
  FD inherit New FD
kill Process sigkill Current Target
    sigstop  
    sigchld  
    signal  
wait Process sigkill Child Current
    sigstop  
    sigchld  
    signal  
fork Process fork Current Current
clone      
uselib Process execute Current File
ptrace Process ptrace Current Target
getpriority Process getsched Current Target
getscheduler      
getparam      
setpriority Process setsched Current Target
setscheduler      
setparam      
getsid Process getsession Current Target
getpgid Process getpgid Current Target
setpgid Process setpgid Current Target
capget Process getcap Current Target
capset Process setcap Current Target


Table 4 shows the control requirements for process management system calls. In it, the control requirements for each system call are specified, where each control requirement is described by the class, permission, source SID, and target SID used in a permission check. Since multiple calls may have the same requirements, more than one call may be listed in the leftmost column of a single table entry. In this case, all of the requirements in that table entry apply to all of the calls. In the table, the path target SID indicates that the permission check should be applied to each directory in the path prefix, and the directory class is abbreviated by dir.

The execve system call is the most complicated process management call to control. There are two relevant file system permission checks, the search check between the process SID and SID of each component of the pathname to verify that the program can be accessed and the execute check between the current process SID and new program's SID to verify that the program can be initiated by a process with that SID. The file system controls are described in Section  6.1. A process execute check between the new process SID and the new program SID is done to verify that the new process image can execute in the security context of the process.

Since Linux supports a variety of binary formats that must be handled during the execve system call, not only must access to the program that is to be executed be controlled, but access to whatever programs are used to support the execution of that program must also be controlled. An example of this is that when a script is executed, access to the script must be checked as well as access to the interpreter of the script. Similarly, execute checks for shared libraries are needed. In addition, execution checks will be placed in the Linux-specific system call, uselib, to control a process' ability to specify a particular shared library during execution.

The ability of a process to change its SID must be carefully controlled. This is done during the execve processing since this is the only place where a process' SID may change. Whether the new SID is specified or results from a default transition, the transition permission is checked between the old and new SIDs, and the entrypoint permission is checked between the new SID and the program SID. SID transitions on executable scripts are not prevented as is currently done in Linux with setuid transitions. Transitions are prevented, however, if the process is sharing parts of the process state, such as the file descriptor table or signal handlers, as could be the case when certain values for the flags are supplied to clone. If the process is being traced, then the ptrace permission is checked between the parent process and the new SID.

When a SID transition does occur it is also necessary to revalidate any descriptors. The need to control file descriptors is further discussed in section  6.1. The inherit permission for file descriptors is checked for each open descriptor. Any descriptor that does not pass the check will be closed. One consequence of this is that it is quite possible that stdin, stdout, and stderr could be unexpectedly closed on an execve. This is only an inconvenience except in the construction of command pipelines. Several options to minimize this impact exist. It may be possible to address this solely within the current framework with correct policy specification. It may prove worthwhile to control these descriptors separately from the rest. It may also be practical to modify the shell or construct special wrapper programs to handle descriptor inheritance and security transitions properly. The issue is still being studied.

The sigkill, sigstop, sigchld and signal permissions were added to control whether particular signals may be sent to a process with a given SID. As signals are only generated from within the kernel or local processes, permission checking will only be done when the signal is sent and will not be required when it is received. Before a signal can be delivered the appropriate permission is checked between the sender and receiver SIDs. Because the fcntl call can be used to set the recipient of a signals generated from asynchronous I/O, the SID of the process must be saved in the description to allow appropriate signal checking to be done when the kernel generates the signal.

The ability of one process to wait on another needs to be controlled because information can be passed with the exit status. Originally, the design called for a process wait permission. It was planned that whenever a security context transition was to occur, this permission would be checked to determine if the parent process would be able to wait on the child. If so, then normal processing could proceed. However, if the parent was to be forbidden to wait on the child, the child would have been reparented to the init process and the parent awakened with an appropriate error status. This approach had to be abandoned because it proved difficult to guarantee the process group semantics of Linux.

The same effect can be more cleanly achieved with the signal permissions. When the wait system call is executed, the process will only be allowed to wait if there is a child process that matches the argument to the call that is permitted to send its exit signal to the process. This exit signal is set during process creation and can not be changed. If the permission check fails and no other matching children processes that can send their exit signal to the parent exist, the calling process is given an error message indicating that no child was found.

When a process undergoes a SID transition, it is possible that the policy will no longer permit a signal to be delivered to any processes waiting on that process when the transformed process terminates. To ensure that a waiting process is not left waiting in such situations, SID transitions cause waiting processes to be awakened. Waiting will continue only if it is in accordance with the policy.

Control of the exit system call is not required. The two issues associated with it, receiving exit status information and being signaled by a child process, are handled by the checking done for the wait call and signal mechanism. A side effect of this decision is that a zombie process may be retained in the process table until its parent dies since its parent may be prevented from reaping it. In that case, the zombied process will have to be reparented to the init process for reaping, a mechanism already present in Linux. To make this design work properly, it must be possible for all processes, regardless of their security domain, to signal the init process to ensure that it will be able to reap orphaned processes. This could be guaranteed using the security policy mechanism or through code modifications to the signal mechanism.

An additional ramification of using signal controls to handle wait and exit notifications comes as a result of a POSIX requirement (POSIX 3.2.2.2) to signal any process group with stopped jobs which becomes orphaned as a result of an exit. If a process has undergone a SID transition after it has done one or more forks, its death will cause a signal to be sent to those children even though the policy might prohibit it.

Linux presents an additional issue with regard to signals and exiting. It is possible for a process to set the signal that it will receive when its parent exits. The checking in the signal mechanism will determine if this signal can be delivered, but it may be desirable to control the ability to use the prctl system call which sets this signal. This issue is still being explored.

Because SID transitions do not occur during the fork system call, most security policies would not require the explicit control of this call. Some policies, however, may have a need to restrict a process' ability to create a new process. The fork permission was added to support such policies. It is checked during calls to fork and its Linux-specific generalization clone.

The ptrace call is controlled using the ptrace permission. This permission is initially checked upon a PTRACE_ATTACH or PTRACE_TRACEME request. In the case of PTRACE_TRACEME, the permission is checked between the parent process and the calling process. Otherwise, it is checked between the calling process and the target process. The permission is also revalidated on the other ptrace requests since the calling process may have changed its SID or the policy may have changed. As described earlier, the ptrace permission is also checked during execve if the SID of a traced process changes. Finally, the ptrace permission is checked when a process attempts to access the mem file of another process in the procfs file system.

The getpriority, sched_getscheduler, and sched_getparam calls are controlled using the getsched permission. The setpriority, sched_setscheduler, and sched_setparam calls are controlled using the setsched permission. The getsid, getpgid, and setpgid calls are controlled using the getsession, getpgid, and setpgid permissions, respectively. The capget and capset calls are controlled using the getcap and setcap permissions, respectively. These permissions are checked between the calling process and the target process if they differ.

Most system calls that require superuser privileges to run should also be controlled by the policy. For these calls, it may only be necessary to assign a permission that determines if a process with a given SID can execute the call. Since the Linux capability mechanism already controls many of these calls, the capability permissions are used to make them subject to the central security policy. The source and target SIDS used in the capability permission checking are both that of the current process. Capabilities are discussed further in Section 10.


Table 5: Process Management System Calls without Control Requirements.
CALL(S) DESCRIPTION
get*uid Obtain current process information
get*gid
getgroups
getitimer
getpgrp
getpid
getppid
getrlimit
getrusage
signal Signal handling
sigaction
sigalstack
sigprocmask
sigpending
sigsuspend
nanosleep Pause execution
pause


System calls that only permit a process to observe its own private state or to modify its own unprivileged private state typically do not require controls. Some of these calls are listed in Table 5. Other process management system calls may need to be controlled by the policy. A review of the system call interface to determine the set of calls that need additional controls is described in Section 10.


\begin{editorialenv}
% latex2html id marker 1880{
Tables~\ref{table:processre...
...ude all PM system calls that do or do not
require control.
}
\end{editorialenv}


next up previous contents
Next: API extensions Up: Design Previous: Permissions   Contents