diff options
-rw-r--r-- | fs/nfs/super.c | 3 | ||||
-rw-r--r-- | include/linux/security.h | 10 | ||||
-rw-r--r-- | security/capability.c | 3 | ||||
-rw-r--r-- | security/security.c | 4 | ||||
-rw-r--r-- | security/selinux/hooks.c | 39 |
5 files changed, 46 insertions, 13 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 95cdcb208dfb..6b4bf7622280 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -2380,10 +2380,9 @@ int nfs_clone_sb_security(struct super_block *s, struct dentry *mntroot, | |||
2380 | struct nfs_mount_info *mount_info) | 2380 | struct nfs_mount_info *mount_info) |
2381 | { | 2381 | { |
2382 | /* clone any lsm security options from the parent to the new sb */ | 2382 | /* clone any lsm security options from the parent to the new sb */ |
2383 | security_sb_clone_mnt_opts(mount_info->cloned->sb, s); | ||
2384 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) | 2383 | if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops) |
2385 | return -ESTALE; | 2384 | return -ESTALE; |
2386 | return 0; | 2385 | return security_sb_clone_mnt_opts(mount_info->cloned->sb, s); |
2387 | } | 2386 | } |
2388 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); | 2387 | EXPORT_SYMBOL_GPL(nfs_clone_sb_security); |
2389 | 2388 | ||
diff --git a/include/linux/security.h b/include/linux/security.h index eee7478cda70..4c7058dc5514 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -1436,7 +1436,7 @@ struct security_operations { | |||
1436 | struct path *new_path); | 1436 | struct path *new_path); |
1437 | int (*sb_set_mnt_opts) (struct super_block *sb, | 1437 | int (*sb_set_mnt_opts) (struct super_block *sb, |
1438 | struct security_mnt_opts *opts); | 1438 | struct security_mnt_opts *opts); |
1439 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, | 1439 | int (*sb_clone_mnt_opts) (const struct super_block *oldsb, |
1440 | struct super_block *newsb); | 1440 | struct super_block *newsb); |
1441 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); | 1441 | int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts); |
1442 | 1442 | ||
@@ -1721,7 +1721,7 @@ int security_sb_mount(const char *dev_name, struct path *path, | |||
1721 | int security_sb_umount(struct vfsmount *mnt, int flags); | 1721 | int security_sb_umount(struct vfsmount *mnt, int flags); |
1722 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); | 1722 | int security_sb_pivotroot(struct path *old_path, struct path *new_path); |
1723 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); | 1723 | int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); |
1724 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 1724 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
1725 | struct super_block *newsb); | 1725 | struct super_block *newsb); |
1726 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 1726 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); |
1727 | 1727 | ||
@@ -2011,9 +2011,11 @@ static inline int security_sb_set_mnt_opts(struct super_block *sb, | |||
2011 | return 0; | 2011 | return 0; |
2012 | } | 2012 | } |
2013 | 2013 | ||
2014 | static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 2014 | static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
2015 | struct super_block *newsb) | 2015 | struct super_block *newsb) |
2016 | { } | 2016 | { |
2017 | return 0; | ||
2018 | } | ||
2017 | 2019 | ||
2018 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 2020 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
2019 | { | 2021 | { |
diff --git a/security/capability.c b/security/capability.c index 579775088967..a6290b625be9 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -98,9 +98,10 @@ static int cap_sb_set_mnt_opts(struct super_block *sb, | |||
98 | return 0; | 98 | return 0; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, | 101 | static int cap_sb_clone_mnt_opts(const struct super_block *oldsb, |
102 | struct super_block *newsb) | 102 | struct super_block *newsb) |
103 | { | 103 | { |
104 | return 0; | ||
104 | } | 105 | } |
105 | 106 | ||
106 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 107 | static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) |
diff --git a/security/security.c b/security/security.c index 7b88c6aeaed4..108281d2307a 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -299,10 +299,10 @@ int security_sb_set_mnt_opts(struct super_block *sb, | |||
299 | } | 299 | } |
300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 300 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
301 | 301 | ||
302 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | 302 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
303 | struct super_block *newsb) | 303 | struct super_block *newsb) |
304 | { | 304 | { |
305 | security_ops->sb_clone_mnt_opts(oldsb, newsb); | 305 | return security_ops->sb_clone_mnt_opts(oldsb, newsb); |
306 | } | 306 | } |
307 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); | 307 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
308 | 308 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2fa28c88900c..3c02be3f6732 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -750,7 +750,37 @@ out_double_mount: | |||
750 | goto out; | 750 | goto out; |
751 | } | 751 | } |
752 | 752 | ||
753 | static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | 753 | static int selinux_cmp_sb_context(const struct super_block *oldsb, |
754 | const struct super_block *newsb) | ||
755 | { | ||
756 | struct superblock_security_struct *old = oldsb->s_security; | ||
757 | struct superblock_security_struct *new = newsb->s_security; | ||
758 | char oldflags = old->flags & SE_MNTMASK; | ||
759 | char newflags = new->flags & SE_MNTMASK; | ||
760 | |||
761 | if (oldflags != newflags) | ||
762 | goto mismatch; | ||
763 | if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid) | ||
764 | goto mismatch; | ||
765 | if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid) | ||
766 | goto mismatch; | ||
767 | if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid) | ||
768 | goto mismatch; | ||
769 | if (oldflags & ROOTCONTEXT_MNT) { | ||
770 | struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security; | ||
771 | struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security; | ||
772 | if (oldroot->sid != newroot->sid) | ||
773 | goto mismatch; | ||
774 | } | ||
775 | return 0; | ||
776 | mismatch: | ||
777 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, " | ||
778 | "different security settings for (dev %s, " | ||
779 | "type %s)\n", newsb->s_id, newsb->s_type->name); | ||
780 | return -EBUSY; | ||
781 | } | ||
782 | |||
783 | static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | ||
754 | struct super_block *newsb) | 784 | struct super_block *newsb) |
755 | { | 785 | { |
756 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; | 786 | 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, | |||
765 | * mount options. thus we can safely deal with this superblock later | 795 | * mount options. thus we can safely deal with this superblock later |
766 | */ | 796 | */ |
767 | if (!ss_initialized) | 797 | if (!ss_initialized) |
768 | return; | 798 | return 0; |
769 | 799 | ||
770 | /* how can we clone if the old one wasn't set up?? */ | 800 | /* how can we clone if the old one wasn't set up?? */ |
771 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 801 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
772 | 802 | ||
773 | /* if fs is reusing a sb, just let its options stand... */ | 803 | /* if fs is reusing a sb, make sure that the contexts match */ |
774 | if (newsbsec->flags & SE_SBINITIALIZED) | 804 | if (newsbsec->flags & SE_SBINITIALIZED) |
775 | return; | 805 | return selinux_cmp_sb_context(oldsb, newsb); |
776 | 806 | ||
777 | mutex_lock(&newsbsec->lock); | 807 | mutex_lock(&newsbsec->lock); |
778 | 808 | ||
@@ -805,6 +835,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
805 | 835 | ||
806 | sb_finish_set_opts(newsb); | 836 | sb_finish_set_opts(newsb); |
807 | mutex_unlock(&newsbsec->lock); | 837 | mutex_unlock(&newsbsec->lock); |
838 | return 0; | ||
808 | } | 839 | } |
809 | 840 | ||
810 | static int selinux_parse_opts_str(char *options, | 841 | static int selinux_parse_opts_str(char *options, |