New System Calls

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 the Section called Internal Architecture, 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 the Section called Extended Socket Call Processing.

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.