Superblock Hook Functions

The SELinux superblock hook function implementations manage the security fields of super_block structures and perform access control for filesystem operations. This section begins by describing the superblock hook functions for managing the security fields. It then discusses the superblock hook functions for performing access control.

Managing Superblock Security Fields

Superblock Security Structure

The superblock_security_struct structure contains security information for superblock objects. This structure is defined as follows:

struct superblock_security_struct {
        struct super_block *sb;
        struct list_head list;
        u32 sid;
        u32 def_sid;
        unsigned int behavior;
        unsigned char initialized;
        unsigned char proc;
        struct semaphore sem;
        struct list_head isec_head;
        spinlock_t isec_lock;
};

Table 9. superblock_security_struct

FieldDescription
sbBack pointer to the associated superblock.
listLink into list of superblock security structures setup prior to initial policy load.
sidSID for the file system.
def_siddefault SID for labeling
behaviorLabeling behavior to apply to inodes.
initializedFlag indicating whether the security structure has been initialized.
semSemaphore used to synchronize initialization.
isec_headList of inode security structures setup prior to superblock security initialization.
isec_lockLock for list of inode security structures.

superblock_alloc_security and superblock_free_security

The superblock_alloc_security and superblock_free_security helper functions are the primitive allocation functions for super_block security structures. The selinux_sb_alloc_security and selinux_sb_free_security hook functions call these helper functions.

superblock_doinit

This helper function performs initialization for superblock security structures. It is normally called by the selinux_sb_kern_mount hook function. However, since this helper function cannot perform full initialization until after the initial policy load, it is also called by the selinux_complete_init function to retroactively complete initialization of superblocks setup prior to the initial policy load.

The superblock_doinit function begins by taking the semaphore to synchronize with any other attempts to initialize the superblock security data and then checks whether the superblock security structure has already been marked initialized. If so, the function returns after releasing the semaphore. Otherwise, it checks whether the initial policy load has completed. If not, then the function adds the superblock security structure to a global list for deferred processing by selinux_complete_init, releases the semaphore and returns.

If the initial policy load has completed, then superblock_doinit calls the security server's security_fs_use interface to determine the labeling behavior for the inodes associated with the superblock and to obtain a SID for the superblock itself. It then calls the try_context_mount to handle any mount context options, which can override the labeling behavior and superblock SID returned by security_fs_use. Context mount support is discussed further in the Section called try_context_mount.

If the desired labeling behavior is to use extended attributes (xattr) superblock_doinit verifies that the filesystem supports xattr and the security namespace, returning an error otherwise. If the superblock is for the proc pseudo filesystem, the function sets the proc flag in the superblock security structure for special handling upon inode initialization. The function then marks the superblock security structure as initialized.

Next, superblock_doinit calls inode_doinit_with_dentry on the root inode to initialize its security structure. The function likewise makes calls to initialize the inode security structures for any inodes that were setup prior to superblock security initialization (e.g. prior to initial policy load or during get_sb by a filesystem that directly populates itself). Finally, the function releases the semaphore and returns.

selinux_sb_copy_data

The selinux_sb_copy_data function is called to allow mount option data to be copied prior to parsing by the filesystem, so that the security module can extract security-specific mount options cleanly, especially since the filesystem code may modify the data while processing. The hook function also allows the security-specific options to be stripped from the mount data so that the filesystem code does not need to be aware of them at all. If the filesystem type uses binary mount data, then this hook function simply copies the binary data into the page for security data for later processing. Otherwise, this hook function parses the mount option string and extracts any mount context options for later use. There are three kinds of mount context options: context, fscontext, and defcontext.

try_context_mount

The try_context_mount function is called to handle any context mount options extracted earlier by selinux_sb_copy_data. If the filesystem type uses binary mount data, then the function will extract context options if using a version of the binary mount data that includes them. At present, only NFS has support for such options, and it only supports one of the context mount options (context=). For string mount data, the function processes each context-related option, checking for invalid combinations. The fscontext and defcontext options may be used together as well as individually, but no other combination of options is allowed. If any context option is specified, the function applies several permission checks among the task SID, the original superblock SID, and the SID for the provided context to verify that the use of the option is authorized.

For the context or fscontext options, the superblock SID is set to the SID for the provided context. The context option further changes the labeling behavior to mountpoint labeling, which means that all inodes in the filesystem are treated as having the provided context as well, and the xattr API is not supported for the inodes in the filesystem even if the filesystem type itself supports xattrs. In contrast, the fscontext option only sets the superblock SID and leaves the labeling behavior unchanged. The defcontext option only sets the default SID (def_sid) for inodes in the filesystem, overriding the typical value of the file initial SID.

selinux_sb_kern_mount

This hook function is called to setup the superblock security structure and to check permissions for the mount of a particular superblock. It calls superblock_doinit to perform the initialization and then calls superblock_has_perm to check filesystem mount permission to the superblock.

Controlling Filesystem Operations

superblock_has_perm

This helper function checks whether a task has a particular permission to a filesystem. It takes the task, the super_block, the requested permissions, and optionally audit data as parameters. This function simply calls the AVC with the appropriate parameters.

selinux_sb_statfs

This hook function is called to check permission when obtaining filesystem attributes. It checks getattr permission between the current task and the filesystem.

selinux_mount

This hook function is called to check permission when mounting a filesystem prior to the actual reading of the superblock. If the filesystem is being remounted (i.e. the mount flags are being changed), then this function checks remount permission between the current task and the filesystem. Otherwise, this function checks mounton permission between the current task and the mountpoint directory.

selinux_umount

This hook function is called to check permission when unmounting a filesystem. This function checks unmount permission between the current task and the filesystem.

selinux_quotactl

The selinux_quotactl hook function checks that the current task has permission to perform a given quota control command on a filesystem. If no filesystem was specified (i.e. a Q_SYNC or Q_GETSTATS command), then the hook simply returns success, since these operations require no control. Otherwise, one of the quotamod or quotaget permissions is checked between the current task and the filesystem, depending on whether the command sets information or merely gets information related to quotas.

Summary of Filesystem Permission Checks

The permission checks for the super_block hooks are summarized in Table 10.

Table 10. Filesystem Permission Checks

HookSourceTargetPermission(s)
selinux_sb_statfsCurrentFilesystemgetattr
selinux_mount

Current
Current

MountDirectory
Filesystem

mounton
remount

selinux_sb_kern_mountCurrentFilesystemmount
selinux_umountCurrentFilesystemunmount
selinux_quotactlCurrentFilesystem

quotamod
quotaget