|
@@ -750,7 +750,37 @@ out_double_mount:
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
-static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
|
+static int selinux_cmp_sb_context(const struct super_block *oldsb,
|
|
|
+ const struct super_block *newsb)
|
|
|
+{
|
|
|
+ struct superblock_security_struct *old = oldsb->s_security;
|
|
|
+ struct superblock_security_struct *new = newsb->s_security;
|
|
|
+ char oldflags = old->flags & SE_MNTMASK;
|
|
|
+ char newflags = new->flags & SE_MNTMASK;
|
|
|
+
|
|
|
+ if (oldflags != newflags)
|
|
|
+ goto mismatch;
|
|
|
+ if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
|
|
|
+ goto mismatch;
|
|
|
+ if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
|
|
|
+ goto mismatch;
|
|
|
+ if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
|
|
|
+ goto mismatch;
|
|
|
+ if (oldflags & ROOTCONTEXT_MNT) {
|
|
|
+ struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
|
|
|
+ struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
|
|
|
+ if (oldroot->sid != newroot->sid)
|
|
|
+ goto mismatch;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+mismatch:
|
|
|
+ printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
|
|
|
+ "different security settings for (dev %s, "
|
|
|
+ "type %s)\n", newsb->s_id, newsb->s_type->name);
|
|
|
+ return -EBUSY;
|
|
|
+}
|
|
|
+
|
|
|
+static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
|
struct super_block *newsb)
|
|
|
{
|
|
|
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
|
|
@@ -765,14 +795,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
|
* mount options. thus we can safely deal with this superblock later
|
|
|
*/
|
|
|
if (!ss_initialized)
|
|
|
- return;
|
|
|
+ return 0;
|
|
|
|
|
|
/* how can we clone if the old one wasn't set up?? */
|
|
|
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
|
|
|
|
|
- /* if fs is reusing a sb, just let its options stand... */
|
|
|
+ /* if fs is reusing a sb, make sure that the contexts match */
|
|
|
if (newsbsec->flags & SE_SBINITIALIZED)
|
|
|
- return;
|
|
|
+ return selinux_cmp_sb_context(oldsb, newsb);
|
|
|
|
|
|
mutex_lock(&newsbsec->lock);
|
|
|
|
|
@@ -805,6 +835,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
|
|
|
|
sb_finish_set_opts(newsb);
|
|
|
mutex_unlock(&newsbsec->lock);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int selinux_parse_opts_str(char *options,
|