This section discusses how the new SELinux system calls were
implemented in the SELinux security module. The code for these calls
can be found in the syscalls.c and
include/asm-i386/flask/syscalls.c files. All of the new
system calls are multiplexed through the security
system call added by LSM. However, SELinux could not use the
sys_security
function and hook provided by LSM,
because they do not provide access to the registers on the stack.
This information is needed by the execve_secure
system call.
Hence, the SELinux security module inserts its own
sys_security_selinux
function into the system
call table during initialization in place of the LSM function. The
SELinux function checks the module identifier to ensure that the
application is invoking a SELinux system call and then calls the
individual function for the requested call with the appropriate
parameters. In the case of execve_secure
, the
entrypoint function also passes a pointer to the registers on the
stack.
As mentioned in Section 6, the implementation of the
extended system calls required a different approach than in the
original SELinux prototype. Since the existing internal kernel
functions could not be extended to pass SIDs, input and output SID
arrays were added to the security structure associated with tasks
(task_security_struct
in
selinux_plug.h). The extended system calls can
set the elements of the in_sid
array in this structure prior to
calling the ordinary system call to pass SIDs to the hook functions
called during the system call. Likewise, the hook functions can set
the elements of the out_sid
array in this structure to pass SIDs back
to the extended system calls for return to the application. Since a
separate Linux task structure is created even when the
clone
call is used to create threads, these
elements should be safe against concurrent access.
The new IPC system calls for obtaining SIDs were not as
straightforward. The semsid
,
shmsid
, and msgsid
calls
could not directly look up the corresponding kernel object due to the
encapsulation of the IPC code, so they had to invoke an actual IPC
operation to permit a hook to obtain the SID and pass it back via the
out_sid
array. The corresponding control operation
(e.g. SEMCTL
) is called with the
IPC_STAT
operation for this purpose, with a
temporary kernel buffer and the data segment set to the kernel segment
to deal with the normal copyout.
Similarly, the msgrcv_secure
call was complicated
by the fact that the sys_msgrcv
function is not exported
directly to modules and the generic ipc
call
expects a userspace ipc_kludge
structure.
This was resolved by using version 1
of the
MSGRCV
IPC call value, thereby avoiding the need
to pass such a structure. In this case, it would not have worked to
simply provide a temporary kernel structure and set the data segment,
because the other parameters include userspace pointers.
The implementation of the extended socket system calls is still in progress, and several issues still remain to be resolved. These issues include passing a message SID and a destination socket SID for a particular outgoing message from the socket layer hooks to the network buffer hooks, and labeling the SYNACK packet with the correct SID when the useclient flag is set. These issues are discussed further in Section 17.4.
The final issue in implementing the new system calls was implementing
the execve_secure
call. As mentioned above, this
call requires access to the registers on the stack, so SELinux had to
provide its own entrypoint function for the
security
system call. This call
parallels the processing of the existing kernel
sys_execve
entrypoint function, copying in the
filename and calling the kernel do_execve
function. It only differs in that it sets an element of the in_sid
array to the specified SID for use by the program loading hook
functions.