Skip to content

Commit cec5fe7

Browse files
WOnder93pcmoore
authored andcommitted
selinux: make labeled NFS work when mounted before policy load
Currently, when an NFS filesystem that supports passing LSM/SELinux labels is mounted during early boot (before the SELinux policy is loaded), it ends up mounted without the labeling support (i.e. with Fedora policy all files get the generic NFS label system_u:object_r:nfs_t:s0). This is because the information that the NFS mount supports passing labels (communicated to the LSM layer via the kern_flags argument of security_set_mnt_opts()) gets lost and when the policy is loaded the mount is initialized as if the passing is not supported. Fix this by noting the "native labeling" in newsbsec->flags (using a new SE_SBNATIVE flag) on the pre-policy-loaded call of selinux_set_mnt_opts() and then making sure it is respected on the second call from delayed_superblock_init(). Additionally, make inode_doinit_with_dentry() initialize the inode's label from its extended attributes whenever it doesn't find it already intitialized by the filesystem. This is needed to properly initialize pre-existing inodes when delayed_superblock_init() is called. It should not trigger in any other cases (and if it does, it's still better to initialize the correct label instead of leaving the inode unlabeled). Fixes: eb9ae68 ("SELinux: Add new labeling type native labels") Tested-by: Scott Mayhew <smayhew@redhat.com> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> [PM: fixed 'Fixes' tag format] Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent 29cd55f commit cec5fe7

2 files changed

Lines changed: 42 additions & 17 deletions

File tree

security/selinux/hooks.c

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -605,26 +605,31 @@ static int selinux_set_mnt_opts(struct super_block *sb,
605605
u32 defcontext_sid = 0;
606606
int rc = 0;
607607

608+
/*
609+
* Specifying internal flags without providing a place to
610+
* place the results is not allowed
611+
*/
612+
if (kern_flags && !set_kern_flags)
613+
return -EINVAL;
614+
608615
mutex_lock(&sbsec->lock);
609616

610617
if (!selinux_initialized()) {
611618
if (!opts) {
612619
/* Defer initialization until selinux_complete_init,
613620
after the initial policy is loaded and the security
614621
server is ready to handle calls. */
622+
if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
623+
sbsec->flags |= SE_SBNATIVE;
624+
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
625+
}
615626
goto out;
616627
}
617628
rc = -EINVAL;
618629
pr_warn("SELinux: Unable to set superblock options "
619630
"before the security server is initialized\n");
620631
goto out;
621632
}
622-
if (kern_flags && !set_kern_flags) {
623-
/* Specifying internal flags without providing a place to
624-
* place the results is not allowed */
625-
rc = -EINVAL;
626-
goto out;
627-
}
628633

629634
/*
630635
* Binary mount data FS will come through this function twice. Once
@@ -757,7 +762,17 @@ static int selinux_set_mnt_opts(struct super_block *sb,
757762
* sets the label used on all file below the mountpoint, and will set
758763
* the superblock context if not already set.
759764
*/
760-
if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
765+
if (sbsec->flags & SE_SBNATIVE) {
766+
/*
767+
* This means we are initializing a superblock that has been
768+
* mounted before the SELinux was initialized and the
769+
* filesystem requested native labeling. We had already
770+
* returned SECURITY_LSM_NATIVE_LABELS in *set_kern_flags
771+
* in the original mount attempt, so now we just need to set
772+
* the SECURITY_FS_USE_NATIVE behavior.
773+
*/
774+
sbsec->behavior = SECURITY_FS_USE_NATIVE;
775+
} else if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
761776
sbsec->behavior = SECURITY_FS_USE_NATIVE;
762777
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
763778
}
@@ -868,32 +883,38 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
868883
int set_context = (oldsbsec->flags & CONTEXT_MNT);
869884
int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT);
870885

871-
/*
872-
* if the parent was able to be mounted it clearly had no special lsm
873-
* mount options. thus we can safely deal with this superblock later
874-
*/
875-
if (!selinux_initialized())
876-
return 0;
877-
878886
/*
879887
* Specifying internal flags without providing a place to
880888
* place the results is not allowed.
881889
*/
882890
if (kern_flags && !set_kern_flags)
883891
return -EINVAL;
884892

893+
mutex_lock(&newsbsec->lock);
894+
895+
/*
896+
* if the parent was able to be mounted it clearly had no special lsm
897+
* mount options. thus we can safely deal with this superblock later
898+
*/
899+
if (!selinux_initialized()) {
900+
if (kern_flags & SECURITY_LSM_NATIVE_LABELS) {
901+
newsbsec->flags |= SE_SBNATIVE;
902+
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
903+
}
904+
goto out;
905+
}
906+
885907
/* how can we clone if the old one wasn't set up?? */
886908
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
887909

888910
/* if fs is reusing a sb, make sure that the contexts match */
889911
if (newsbsec->flags & SE_SBINITIALIZED) {
912+
mutex_unlock(&newsbsec->lock);
890913
if ((kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context)
891914
*set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
892915
return selinux_cmp_sb_context(oldsb, newsb);
893916
}
894917

895-
mutex_lock(&newsbsec->lock);
896-
897918
newsbsec->flags = oldsbsec->flags;
898919

899920
newsbsec->sid = oldsbsec->sid;
@@ -1394,8 +1415,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
13941415
spin_unlock(&isec->lock);
13951416

13961417
switch (sbsec->behavior) {
1418+
/*
1419+
* In case of SECURITY_FS_USE_NATIVE we need to re-fetch the labels
1420+
* via xattr when called from delayed_superblock_init().
1421+
*/
13971422
case SECURITY_FS_USE_NATIVE:
1398-
break;
13991423
case SECURITY_FS_USE_XATTR:
14001424
if (!(inode->i_opflags & IOP_XATTR)) {
14011425
sid = sbsec->def_sid;

security/selinux/include/security.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#define SE_SBPROC 0x0200
6666
#define SE_SBGENFS 0x0400
6767
#define SE_SBGENFS_XATTR 0x0800
68+
#define SE_SBNATIVE 0x1000
6869

6970
#define CONTEXT_STR "context"
7071
#define FSCONTEXT_STR "fscontext"

0 commit comments

Comments
 (0)