aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/super.c3
-rw-r--r--include/linux/security.h10
-rw-r--r--security/capability.c3
-rw-r--r--security/security.c4
-rw-r--r--security/selinux/hooks.c39
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}
2388EXPORT_SYMBOL_GPL(nfs_clone_sb_security); 2387EXPORT_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,
1721int security_sb_umount(struct vfsmount *mnt, int flags); 1721int security_sb_umount(struct vfsmount *mnt, int flags);
1722int security_sb_pivotroot(struct path *old_path, struct path *new_path); 1722int security_sb_pivotroot(struct path *old_path, struct path *new_path);
1723int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts); 1723int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
1724void security_sb_clone_mnt_opts(const struct super_block *oldsb, 1724int security_sb_clone_mnt_opts(const struct super_block *oldsb,
1725 struct super_block *newsb); 1725 struct super_block *newsb);
1726int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); 1726int 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
2014static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb, 2014static 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
2018static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 2020static 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
101static void cap_sb_clone_mnt_opts(const struct super_block *oldsb, 101static 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
106static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) 107static 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}
300EXPORT_SYMBOL(security_sb_set_mnt_opts); 300EXPORT_SYMBOL(security_sb_set_mnt_opts);
301 301
302void security_sb_clone_mnt_opts(const struct super_block *oldsb, 302int 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}
307EXPORT_SYMBOL(security_sb_clone_mnt_opts); 307EXPORT_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
753static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, 753static 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;
776mismatch:
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
783static 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
810static int selinux_parse_opts_str(char *options, 841static int selinux_parse_opts_str(char *options,