The kernel's file structure represents an open filesystem object. It contains the file_operations structure, which describes the operations that can be done to a file. For example, a file can be read from and written to, seeked through, mapped into memory, and so on. Similar to the inode hooks, LSM provides file hooks to mediate access to files, many of which mirror the file_operations. A security field has been added to the file structure for labelling.
When a file is opened, a new file object is created. At this time, the alloc_security() file hook is called to allocate a security field and label the file. This label persists until the file is closed, when the free_security() file hook is called to free the security field.
The permission() file hook can be used to revalidate read and write permissions at each file read or write. This is not effective against reading and writing of memory mapped files, and the changes required to support this page level revalidation are considered too invasive. Actually mapping a file is, however, protected with the mmap() file hook. And changing the protection bits on mapped file regions must pass the mprotect() file hook.
When using file locks to synchronize multiple readers or writers, a task must pass the lock() file hook permission check before performing any locking operation on a file.
If the O_ASYNC flag is set on a file, asynchronous I/O ready signals are delivered to the file owner when the file is ready for input or output. The ability to specify the task that will receive the I/O ready signals is protected by the set_fowner() file hook. Also, the actual signal delivery is mediated by the send_sigiotask() file hook.
Miscellaneous file operations that come through the ioctl(2) and fcntl(2) interfaces are protected by the ioctl() and fcntl() file hooks respectively. Another miscellaneous action protected by the file hooks is the ability to receive an open file descriptor through a socket control message. This action is protected by the receive() file hook.