Skip to content

Commit b8b87fd

Browse files
scottmayhewpcmoore
authored andcommitted
selinux: Fix selinux_sb_mnt_opts_compat()
selinux_sb_mnt_opts_compat() is called under the sb_lock spinlock and shouldn't be performing any memory allocations. Fix this by parsing the sids at the same time we're chopping up the security mount options string and then using the pre-parsed sids when doing the comparison. Fixes: cc274ae ("selinux: fix sleeping function called from invalid context") Fixes: 69c4a42 ("lsm,selinux: add new hook to compare new mount to an existing mount") Signed-off-by: Scott Mayhew <smayhew@redhat.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent ecff305 commit b8b87fd

1 file changed

Lines changed: 41 additions & 34 deletions

File tree

security/selinux/hooks.c

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,10 @@ static void inode_free_security(struct inode *inode)
341341

342342
struct selinux_mnt_opts {
343343
const char *fscontext, *context, *rootcontext, *defcontext;
344+
u32 fscontext_sid;
345+
u32 context_sid;
346+
u32 rootcontext_sid;
347+
u32 defcontext_sid;
344348
};
345349

346350
static void selinux_free_mnt_opts(void *mnt_opts)
@@ -597,15 +601,14 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
597601
return 0;
598602
}
599603

600-
static int parse_sid(struct super_block *sb, const char *s, u32 *sid,
601-
gfp_t gfp)
604+
static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
602605
{
603606
int rc = security_context_str_to_sid(&selinux_state, s,
604-
sid, gfp);
607+
sid, GFP_KERNEL);
605608
if (rc)
606609
pr_warn("SELinux: security_context_str_to_sid"
607610
"(%s) failed for (dev %s, type %s) errno=%d\n",
608-
s, sb->s_id, sb->s_type->name, rc);
611+
s, sb ? sb->s_id : "?", sb ? sb->s_type->name : "?", rc);
609612
return rc;
610613
}
611614

@@ -672,8 +675,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
672675
*/
673676
if (opts) {
674677
if (opts->fscontext) {
675-
rc = parse_sid(sb, opts->fscontext, &fscontext_sid,
676-
GFP_KERNEL);
678+
rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
677679
if (rc)
678680
goto out;
679681
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
@@ -682,8 +684,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
682684
sbsec->flags |= FSCONTEXT_MNT;
683685
}
684686
if (opts->context) {
685-
rc = parse_sid(sb, opts->context, &context_sid,
686-
GFP_KERNEL);
687+
rc = parse_sid(sb, opts->context, &context_sid);
687688
if (rc)
688689
goto out;
689690
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
@@ -692,8 +693,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
692693
sbsec->flags |= CONTEXT_MNT;
693694
}
694695
if (opts->rootcontext) {
695-
rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid,
696-
GFP_KERNEL);
696+
rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
697697
if (rc)
698698
goto out;
699699
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
@@ -702,8 +702,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
702702
sbsec->flags |= ROOTCONTEXT_MNT;
703703
}
704704
if (opts->defcontext) {
705-
rc = parse_sid(sb, opts->defcontext, &defcontext_sid,
706-
GFP_KERNEL);
705+
rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
707706
if (rc)
708707
goto out;
709708
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
@@ -995,21 +994,29 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
995994
if (opts->context || opts->defcontext)
996995
goto err;
997996
opts->context = s;
997+
if (selinux_initialized(&selinux_state))
998+
parse_sid(NULL, s, &opts->context_sid);
998999
break;
9991000
case Opt_fscontext:
10001001
if (opts->fscontext)
10011002
goto err;
10021003
opts->fscontext = s;
1004+
if (selinux_initialized(&selinux_state))
1005+
parse_sid(NULL, s, &opts->fscontext_sid);
10031006
break;
10041007
case Opt_rootcontext:
10051008
if (opts->rootcontext)
10061009
goto err;
10071010
opts->rootcontext = s;
1011+
if (selinux_initialized(&selinux_state))
1012+
parse_sid(NULL, s, &opts->rootcontext_sid);
10081013
break;
10091014
case Opt_defcontext:
10101015
if (opts->context || opts->defcontext)
10111016
goto err;
10121017
opts->defcontext = s;
1018+
if (selinux_initialized(&selinux_state))
1019+
parse_sid(NULL, s, &opts->defcontext_sid);
10131020
break;
10141021
}
10151022

@@ -2647,8 +2654,6 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
26472654
{
26482655
struct selinux_mnt_opts *opts = mnt_opts;
26492656
struct superblock_security_struct *sbsec = selinux_superblock(sb);
2650-
u32 sid;
2651-
int rc;
26522657

26532658
/*
26542659
* Superblock not initialized (i.e. no options) - reject if any
@@ -2665,34 +2670,36 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
26652670
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
26662671

26672672
if (opts->fscontext) {
2668-
rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT);
2669-
if (rc)
2673+
if (opts->fscontext_sid == SECSID_NULL)
26702674
return 1;
2671-
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
2675+
else if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
2676+
opts->fscontext_sid))
26722677
return 1;
26732678
}
26742679
if (opts->context) {
2675-
rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT);
2676-
if (rc)
2680+
if (opts->context_sid == SECSID_NULL)
26772681
return 1;
2678-
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
2682+
else if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
2683+
opts->context_sid))
26792684
return 1;
26802685
}
26812686
if (opts->rootcontext) {
2682-
struct inode_security_struct *root_isec;
2683-
2684-
root_isec = backing_inode_security(sb->s_root);
2685-
rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT);
2686-
if (rc)
2687-
return 1;
2688-
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
2687+
if (opts->rootcontext_sid == SECSID_NULL)
26892688
return 1;
2689+
else {
2690+
struct inode_security_struct *root_isec;
2691+
2692+
root_isec = backing_inode_security(sb->s_root);
2693+
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
2694+
opts->rootcontext_sid))
2695+
return 1;
2696+
}
26902697
}
26912698
if (opts->defcontext) {
2692-
rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT);
2693-
if (rc)
2699+
if (opts->defcontext_sid == SECSID_NULL)
26942700
return 1;
2695-
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
2701+
else if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
2702+
opts->defcontext_sid))
26962703
return 1;
26972704
}
26982705
return 0;
@@ -2712,14 +2719,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
27122719
return 0;
27132720

27142721
if (opts->fscontext) {
2715-
rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL);
2722+
rc = parse_sid(sb, opts->fscontext, &sid);
27162723
if (rc)
27172724
return rc;
27182725
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
27192726
goto out_bad_option;
27202727
}
27212728
if (opts->context) {
2722-
rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL);
2729+
rc = parse_sid(sb, opts->context, &sid);
27232730
if (rc)
27242731
return rc;
27252732
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
@@ -2728,14 +2735,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
27282735
if (opts->rootcontext) {
27292736
struct inode_security_struct *root_isec;
27302737
root_isec = backing_inode_security(sb->s_root);
2731-
rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL);
2738+
rc = parse_sid(sb, opts->rootcontext, &sid);
27322739
if (rc)
27332740
return rc;
27342741
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
27352742
goto out_bad_option;
27362743
}
27372744
if (opts->defcontext) {
2738-
rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL);
2745+
rc = parse_sid(sb, opts->defcontext, &sid);
27392746
if (rc)
27402747
return rc;
27412748
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))

0 commit comments

Comments
 (0)