diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7171a957b933..feb2f42c5a07 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -751,7 +751,37 @@ out_double_mount: | |||
751 | goto out; | 751 | goto out; |
752 | } | 752 | } |
753 | 753 | ||
754 | static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | 754 | static int selinux_cmp_sb_context(const struct super_block *oldsb, |
755 | const struct super_block *newsb) | ||
756 | { | ||
757 | struct superblock_security_struct *old = oldsb->s_security; | ||
758 | struct superblock_security_struct *new = newsb->s_security; | ||
759 | char oldflags = old->flags & SE_MNTMASK; | ||
760 | char newflags = new->flags & SE_MNTMASK; | ||
761 | |||
762 | if (oldflags != newflags) | ||
763 | goto mismatch; | ||
764 | if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid) | ||
765 | goto mismatch; | ||
766 | if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid) | ||
767 | goto mismatch; | ||
768 | if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid) | ||
769 | goto mismatch; | ||
770 | if (oldflags & ROOTCONTEXT_MNT) { | ||
771 | struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security; | ||
772 | struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security; | ||
773 | if (oldroot->sid != newroot->sid) | ||
774 | goto mismatch; | ||
775 | } | ||
776 | return 0; | ||
777 | mismatch: | ||
778 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, " | ||
779 | "different security settings for (dev %s, " | ||
780 | "type %s)\n", newsb->s_id, newsb->s_type->name); | ||
781 | return -EBUSY; | ||
782 | } | ||
783 | |||
784 | static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | ||
755 | struct super_block *newsb) | 785 | struct super_block *newsb) |
756 | { | 786 | { |
757 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; | 787 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; |
@@ -766,14 +796,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
766 | * mount options. thus we can safely deal with this superblock later | 796 | * mount options. thus we can safely deal with this superblock later |
767 | */ | 797 | */ |
768 | if (!ss_initialized) | 798 | if (!ss_initialized) |
769 | return; | 799 | return 0; |
770 | 800 | ||
771 | /* how can we clone if the old one wasn't set up?? */ | 801 | /* how can we clone if the old one wasn't set up?? */ |
772 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 802 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
773 | 803 | ||
774 | /* if fs is reusing a sb, just let its options stand... */ | 804 | /* if fs is reusing a sb, make sure that the contexts match */ |
775 | if (newsbsec->flags & SE_SBINITIALIZED) | 805 | if (newsbsec->flags & SE_SBINITIALIZED) |
776 | return; | 806 | return selinux_cmp_sb_context(oldsb, newsb); |
777 | 807 | ||
778 | mutex_lock(&newsbsec->lock); | 808 | mutex_lock(&newsbsec->lock); |
779 | 809 | ||
@@ -806,6 +836,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
806 | 836 | ||
807 | sb_finish_set_opts(newsb); | 837 | sb_finish_set_opts(newsb); |
808 | mutex_unlock(&newsbsec->lock); | 838 | mutex_unlock(&newsbsec->lock); |
839 | return 0; | ||
809 | } | 840 | } |
810 | 841 | ||
811 | static int selinux_parse_opts_str(char *options, | 842 | static int selinux_parse_opts_str(char *options, |