|
|
@@ -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,
|