mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
security/selinux: allow security_sb_clone_mnt_opts to enable/disable native labeling behavior
When an NFSv4 client performs a mount operation, it first mounts the NFSv4 root and then does path walk to the exported path and performs a submount on that, cloning the security mount options from the root's superblock to the submount's superblock in the process. Unless the NFS server has an explicit fsid=0 export with the "security_label" option, the NFSv4 root superblock will not have SBLABEL_MNT set, and neither will the submount superblock after cloning the security mount options. As a result, setxattr's of security labels over NFSv4.2 will fail. In a similar fashion, NFSv4.2 mounts mounted with the context= mount option will not show the correct labels because the nfs_server->caps flags of the cloned superblock will still have NFS_CAP_SECURITY_LABEL set. Allowing the NFSv4 client to enable or disable SECURITY_LSM_NATIVE_LABELS behavior will ensure that the SBLABEL_MNT flag has the correct value when the client traverses from an exported path without the "security_label" option to one with the "security_label" option and vice versa. Similarly, checking to see if SECURITY_LSM_NATIVE_LABELS is set upon return from security_sb_clone_mnt_opts() and clearing NFS_CAP_SECURITY_LABEL if necessary will allow the correct labels to be displayed for NFSv4.2 mounts mounted with the context= mount option. Resolves: https://github.com/SELinuxProject/selinux-kernel/issues/35 Signed-off-by: Scott Mayhew <[email protected]> Reviewed-by: Stephen Smalley <[email protected]> Tested-by: Stephen Smalley <[email protected]> Signed-off-by: Paul Moore <[email protected]>
This commit is contained in:
parent
b4958c892e
commit
0b4d3452b8
5 changed files with 63 additions and 8 deletions
|
|
@ -525,8 +525,16 @@ static int sb_finish_set_opts(struct super_block *sb)
|
|||
}
|
||||
|
||||
sbsec->flags |= SE_SBINITIALIZED;
|
||||
|
||||
/*
|
||||
* Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
|
||||
* leave the flag untouched because sb_clone_mnt_opts might be handing
|
||||
* us a superblock that needs the flag to be cleared.
|
||||
*/
|
||||
if (selinux_is_sblabel_mnt(sb))
|
||||
sbsec->flags |= SBLABEL_MNT;
|
||||
else
|
||||
sbsec->flags &= ~SBLABEL_MNT;
|
||||
|
||||
/* Initialize the root inode. */
|
||||
rc = inode_doinit_with_dentry(root_inode, root);
|
||||
|
|
@ -959,8 +967,11 @@ mismatch:
|
|||
}
|
||||
|
||||
static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
||||
struct super_block *newsb)
|
||||
struct super_block *newsb,
|
||||
unsigned long kern_flags,
|
||||
unsigned long *set_kern_flags)
|
||||
{
|
||||
int rc = 0;
|
||||
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
|
||||
struct superblock_security_struct *newsbsec = newsb->s_security;
|
||||
|
||||
|
|
@ -975,6 +986,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||
if (!ss_initialized)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Specifying internal flags without providing a place to
|
||||
* place the results is not allowed.
|
||||
*/
|
||||
if (kern_flags && !set_kern_flags)
|
||||
return -EINVAL;
|
||||
|
||||
/* how can we clone if the old one wasn't set up?? */
|
||||
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
||||
|
||||
|
|
@ -990,6 +1008,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||
newsbsec->def_sid = oldsbsec->def_sid;
|
||||
newsbsec->behavior = oldsbsec->behavior;
|
||||
|
||||
if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
|
||||
!(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
|
||||
rc = security_fs_use(newsb);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
|
||||
newsbsec->behavior = SECURITY_FS_USE_NATIVE;
|
||||
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||
}
|
||||
|
||||
if (set_context) {
|
||||
u32 sid = oldsbsec->mntpoint_sid;
|
||||
|
||||
|
|
@ -1009,8 +1039,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|||
}
|
||||
|
||||
sb_finish_set_opts(newsb);
|
||||
out:
|
||||
mutex_unlock(&newsbsec->lock);
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int selinux_parse_opts_str(char *options,
|
||||
|
|
|
|||
Loading…
Reference in a new issue