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 {
        unsigned long magic;
        struct super_block *sb;
        struct list_head list;
        security_id_t sid;
        struct psidtab *psidtab;
        unsigned char uses_psids;
        unsigned char initialized;
        unsigned long initializing;
        unsigned char uses_task;
        struct semaphore sem;
};

Table 7. superblock_security_struct

FieldDescription
magicModule id for the SELinux module.
sbBack pointer to the associated superblock.
listPointer used to maintain the list of allocated superblock security structures.
sidSID for the file system.
uses_psidsFlag indicating whether or not the file system uses persistent SIDs.
initializedFlag indicating whether the security structure has been initialized.
initializingFlag indicating whether the security structure is in the process of being initialized.
uses_taskFlag indicating whether inodes in this filesystem should inherit the SID of the creating task (e.g. pipes, sockets).
semSemaphore used to synchronize filesystem relabels.

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_precondition

This helper function is the precondition function for super_block security structures. This function ensures that the super_block security structure is allocated and initialized prior to use. If the filesystem can use the persistent label mapping, then the psid_init function is called to initialize the mapping and to set the SID of the super_block. This is used for regular persistent filesystem types like ext2 and reiserfs. If the filesystem is a pseudo filesystem for private objects such as pipes or sockets, then a flag is set to indicate that inodes associated with the filesystem should inherit the SID of the creating process. If the filesystem is a pseudo filesystem like procfs, devpts, tmpfs, or devfs, then an appropriate initial SID is assigned to the super_block.

selinux_post_mountroot

This hook function is called after the root filesystem has been mounted. If the security server has not yet been initialized, this function calls the security_init function to initialize the security server and load the initial policy configuration. A failure at this point is fatal unless the development module option is enabled, in which case SELinux will defer initialization and processing until a subsequent policy load or AVC toggle. If the security server has already been initialized (i.e. the hook has been called twice due to a change_root for an initrd), then this hook function tries to reload the policy from the new root filesystem. If the reload fails due to either a lack of permission for the current process or a lack of a policy on the new root filesystem, then SELinux will continue operating under the old (initrd) policy. The hook function then calls the superblock_precondition function on the root filesystem to initialize its persistent label mapping.

selinux_post_pivotroot

This hook function is called after a successful pivot of the root filesystem via the pivot_root system call, typically when an initrd is used. This hook function tries to reload the policy from the new root filesystem. If the reload fails due to either a lack of permission for the current process or a lack of a policy on the new root filesystem, then SELinux will continue operating under the old (initrd) policy.

selinux_post_addmount

This hook function is called after a non-root filesystem has been mounted. It calls superblock_precondition to initialize the persistent label mapping of the filesystem. However, this is obsoleted by the newer selinux_check_sb hook and will be reduced to doing nothing in the future.

selinux_post_remount

This hook function is called after a successful remount of a filesystem (i.e. after the mount flags have been changed). If the filesystem uses the persistent label mapping, then this hook calls the psid_remount function to update the mapping at this time if the filesystem was previously mounted read-only and is now mounted read-write.

selinux_umount_close

This hook function is called when a filesystem is being unmounted prior to checking whether the filesystem is busy. If the filesystem uses the persistent label mapping, then this hook calls the psid_release to free any memory and release any files used for the mapping.

selinux_umount_busy

This hook function is called when the kernel determines that a filesystem cannot be unmounted (e.g. the filesystem is busy) after calling the umount_close hook. If the filesystem uses the persistent label mapping, then this hook function calls psid_init to reinitialize the mapping.

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. It also saves the SID of the filesystem in an element of the out_sid array in the task security structure for use by the statfs_secure system calls.

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_check_sb

This hook function is called to check permission when mounting a filesystem after reading the superblock. This function checks mount permission between the current task and the filesystem. Prior to checking permission, superblock_precondition is called, so the persistent label mapping for the filesystem will be initialized by this hook.

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_pivotroot

This (recently added) hook function is called to check permission when pivoting the root filesystem. Since the pivot_root system call also invokes the capable function with the CAP_SYS_ADMIN capability, the SELinux module already requires that the current process have permission to use this capability. This hook enables security modules to impose finer-grained restrictions on the use of the operation, e.g. distinguishing the operation from other operations that use the same capability and basing decisions on the security attributes of the new root filesystem. The SELinux module does not yet take advantage of this ability, but a finer-grained permission check is planned for the future.

Summary of Filesystem Permission Checks

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

Table 8. Filesystem Permission Checks

HookSourceTargetPermission(s)
selinux_sb_statfsCurrentFilesystemgetattr
selinux_mount

Current
Current

MountDirectory
Filesystem

mounton
remount

selinux_check_sbCurrentFilesystemmount
selinux_umountCurrentFilesystemunmount