Skip to content

Commit 70f4169

Browse files
WOnder93pcmoore
authored andcommitted
selinux: parse contexts for mount options early
Commit b8b87fd ("selinux: Fix selinux_sb_mnt_opts_compat()") started to parse mount options into SIDs in selinux_add_opt() if policy has already been loaded. Since it's extremely unlikely that anyone would depend on the ability to set SELinux contexts on fs_context before loading the policy and then mounting that context after simplify the logic by always parsing the options early. Note that the multi-step mounting is only possible with the new fscontext mount API and wasn't possible before its introduction. Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
1 parent 0e326df commit 70f4169

1 file changed

Lines changed: 53 additions & 149 deletions

File tree

security/selinux/hooks.c

Lines changed: 53 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,6 @@ static void inode_free_security(struct inode *inode)
340340
}
341341

342342
struct selinux_mnt_opts {
343-
const char *fscontext, *context, *rootcontext, *defcontext;
344343
u32 fscontext_sid;
345344
u32 context_sid;
346345
u32 rootcontext_sid;
@@ -349,12 +348,7 @@ struct selinux_mnt_opts {
349348

350349
static void selinux_free_mnt_opts(void *mnt_opts)
351350
{
352-
struct selinux_mnt_opts *opts = mnt_opts;
353-
kfree(opts->fscontext);
354-
kfree(opts->context);
355-
kfree(opts->rootcontext);
356-
kfree(opts->defcontext);
357-
kfree(opts);
351+
kfree(mnt_opts);
358352
}
359353

360354
enum {
@@ -601,17 +595,6 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
601595
return 0;
602596
}
603597

604-
static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
605-
{
606-
int rc = security_context_str_to_sid(&selinux_state, s,
607-
sid, GFP_KERNEL);
608-
if (rc)
609-
pr_warn("SELinux: security_context_str_to_sid"
610-
"(%s) failed for (dev %s, type %s) errno=%d\n",
611-
s, sb ? sb->s_id : "?", sb ? sb->s_type->name : "?", rc);
612-
return rc;
613-
}
614-
615598
/*
616599
* Allow filesystems with binary mount data to explicitly set mount point
617600
* labeling information.
@@ -674,49 +657,29 @@ static int selinux_set_mnt_opts(struct super_block *sb,
674657
* than once with different security options.
675658
*/
676659
if (opts) {
677-
if (opts->fscontext) {
678-
if (opts->fscontext_sid == SECSID_NULL) {
679-
rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
680-
if (rc)
681-
goto out;
682-
} else
683-
fscontext_sid = opts->fscontext_sid;
660+
if (opts->fscontext_sid) {
661+
fscontext_sid = opts->fscontext_sid;
684662
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
685663
fscontext_sid))
686664
goto out_double_mount;
687665
sbsec->flags |= FSCONTEXT_MNT;
688666
}
689-
if (opts->context) {
690-
if (opts->context_sid == SECSID_NULL) {
691-
rc = parse_sid(sb, opts->context, &context_sid);
692-
if (rc)
693-
goto out;
694-
} else
695-
context_sid = opts->context_sid;
667+
if (opts->context_sid) {
668+
context_sid = opts->context_sid;
696669
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
697670
context_sid))
698671
goto out_double_mount;
699672
sbsec->flags |= CONTEXT_MNT;
700673
}
701-
if (opts->rootcontext) {
702-
if (opts->rootcontext_sid == SECSID_NULL) {
703-
rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
704-
if (rc)
705-
goto out;
706-
} else
707-
rootcontext_sid = opts->rootcontext_sid;
674+
if (opts->rootcontext_sid) {
675+
rootcontext_sid = opts->rootcontext_sid;
708676
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
709677
rootcontext_sid))
710678
goto out_double_mount;
711679
sbsec->flags |= ROOTCONTEXT_MNT;
712680
}
713-
if (opts->defcontext) {
714-
if (opts->defcontext_sid == SECSID_NULL) {
715-
rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
716-
if (rc)
717-
goto out;
718-
} else
719-
defcontext_sid = opts->defcontext_sid;
681+
if (opts->defcontext_sid) {
682+
defcontext_sid = opts->defcontext_sid;
720683
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
721684
defcontext_sid))
722685
goto out_double_mount;
@@ -986,13 +949,20 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
986949
{
987950
struct selinux_mnt_opts *opts = *mnt_opts;
988951
bool is_alloc_opts = false;
952+
u32 *dst_sid;
953+
int rc;
989954

990955
if (token == Opt_seclabel)
991956
/* eaten and completely ignored */
992957
return 0;
993958
if (!s)
994959
return -ENOMEM;
995960

961+
if (!selinux_initialized(&selinux_state)) {
962+
pr_warn("SELinux: Unable to set superblock options before the security server is initialized\n");
963+
return -EINVAL;
964+
}
965+
996966
if (!opts) {
997967
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
998968
if (!opts)
@@ -1003,36 +973,34 @@ static int selinux_add_opt(int token, const char *s, void **mnt_opts)
1003973

1004974
switch (token) {
1005975
case Opt_context:
1006-
if (opts->context || opts->defcontext)
976+
if (opts->context_sid || opts->defcontext_sid)
1007977
goto err;
1008-
opts->context = s;
1009-
if (selinux_initialized(&selinux_state))
1010-
parse_sid(NULL, s, &opts->context_sid);
978+
dst_sid = &opts->context_sid;
1011979
break;
1012980
case Opt_fscontext:
1013-
if (opts->fscontext)
981+
if (opts->fscontext_sid)
1014982
goto err;
1015-
opts->fscontext = s;
1016-
if (selinux_initialized(&selinux_state))
1017-
parse_sid(NULL, s, &opts->fscontext_sid);
983+
dst_sid = &opts->fscontext_sid;
1018984
break;
1019985
case Opt_rootcontext:
1020-
if (opts->rootcontext)
986+
if (opts->rootcontext_sid)
1021987
goto err;
1022-
opts->rootcontext = s;
1023-
if (selinux_initialized(&selinux_state))
1024-
parse_sid(NULL, s, &opts->rootcontext_sid);
988+
dst_sid = &opts->rootcontext_sid;
1025989
break;
1026990
case Opt_defcontext:
1027-
if (opts->context || opts->defcontext)
991+
if (opts->context_sid || opts->defcontext_sid)
1028992
goto err;
1029-
opts->defcontext = s;
1030-
if (selinux_initialized(&selinux_state))
1031-
parse_sid(NULL, s, &opts->defcontext_sid);
993+
dst_sid = &opts->defcontext_sid;
1032994
break;
995+
default:
996+
WARN_ON(1);
997+
return -EINVAL;
1033998
}
1034-
1035-
return 0;
999+
rc = security_context_str_to_sid(&selinux_state, s, dst_sid, GFP_KERNEL);
1000+
if (rc)
1001+
pr_warn("SELinux: security_context_str_to_sid (%s) failed with errno=%d\n",
1002+
s, rc);
1003+
return rc;
10361004

10371005
err:
10381006
if (is_alloc_opts) {
@@ -2681,37 +2649,27 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
26812649
if (!opts)
26822650
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
26832651

2684-
if (opts->fscontext) {
2685-
if (opts->fscontext_sid == SECSID_NULL)
2686-
return 1;
2687-
else if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
2688-
opts->fscontext_sid))
2652+
if (opts->fscontext_sid) {
2653+
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
2654+
opts->fscontext_sid))
26892655
return 1;
26902656
}
2691-
if (opts->context) {
2692-
if (opts->context_sid == SECSID_NULL)
2693-
return 1;
2694-
else if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
2695-
opts->context_sid))
2657+
if (opts->context_sid) {
2658+
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
2659+
opts->context_sid))
26962660
return 1;
26972661
}
2698-
if (opts->rootcontext) {
2699-
if (opts->rootcontext_sid == SECSID_NULL)
2700-
return 1;
2701-
else {
2702-
struct inode_security_struct *root_isec;
2662+
if (opts->rootcontext_sid) {
2663+
struct inode_security_struct *root_isec;
27032664

2704-
root_isec = backing_inode_security(sb->s_root);
2705-
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
2706-
opts->rootcontext_sid))
2707-
return 1;
2708-
}
2709-
}
2710-
if (opts->defcontext) {
2711-
if (opts->defcontext_sid == SECSID_NULL)
2665+
root_isec = backing_inode_security(sb->s_root);
2666+
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
2667+
opts->rootcontext_sid))
27122668
return 1;
2713-
else if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
2714-
opts->defcontext_sid))
2669+
}
2670+
if (opts->defcontext_sid) {
2671+
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
2672+
opts->defcontext_sid))
27152673
return 1;
27162674
}
27172675
return 0;
@@ -2721,55 +2679,31 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
27212679
{
27222680
struct selinux_mnt_opts *opts = mnt_opts;
27232681
struct superblock_security_struct *sbsec = selinux_superblock(sb);
2724-
int rc;
27252682

27262683
if (!(sbsec->flags & SE_SBINITIALIZED))
27272684
return 0;
27282685

27292686
if (!opts)
27302687
return 0;
27312688

2732-
if (opts->fscontext) {
2733-
if (opts->fscontext_sid == SECSID_NULL) {
2734-
rc = parse_sid(sb, opts->fscontext,
2735-
&opts->fscontext_sid);
2736-
if (rc)
2737-
return rc;
2738-
}
2689+
if (opts->fscontext_sid) {
27392690
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
27402691
opts->fscontext_sid))
27412692
goto out_bad_option;
27422693
}
2743-
if (opts->context) {
2744-
if (opts->context_sid == SECSID_NULL) {
2745-
rc = parse_sid(sb, opts->context, &opts->context_sid);
2746-
if (rc)
2747-
return rc;
2748-
}
2694+
if (opts->context_sid) {
27492695
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
27502696
opts->context_sid))
27512697
goto out_bad_option;
27522698
}
2753-
if (opts->rootcontext) {
2699+
if (opts->rootcontext_sid) {
27542700
struct inode_security_struct *root_isec;
27552701
root_isec = backing_inode_security(sb->s_root);
2756-
if (opts->rootcontext_sid == SECSID_NULL) {
2757-
rc = parse_sid(sb, opts->rootcontext,
2758-
&opts->rootcontext_sid);
2759-
if (rc)
2760-
return rc;
2761-
}
27622702
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
27632703
opts->rootcontext_sid))
27642704
goto out_bad_option;
27652705
}
2766-
if (opts->defcontext) {
2767-
if (opts->defcontext_sid == SECSID_NULL) {
2768-
rc = parse_sid(sb, opts->defcontext,
2769-
&opts->defcontext_sid);
2770-
if (rc)
2771-
return rc;
2772-
}
2706+
if (opts->defcontext_sid) {
27732707
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
27742708
opts->defcontext_sid))
27752709
goto out_bad_option;
@@ -2838,42 +2772,12 @@ static int selinux_fs_context_dup(struct fs_context *fc,
28382772
struct fs_context *src_fc)
28392773
{
28402774
const struct selinux_mnt_opts *src = src_fc->security;
2841-
struct selinux_mnt_opts *opts;
28422775

28432776
if (!src)
28442777
return 0;
28452778

2846-
fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
2847-
if (!fc->security)
2848-
return -ENOMEM;
2849-
2850-
opts = fc->security;
2851-
2852-
if (src->fscontext) {
2853-
opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
2854-
if (!opts->fscontext)
2855-
return -ENOMEM;
2856-
}
2857-
if (src->context) {
2858-
opts->context = kstrdup(src->context, GFP_KERNEL);
2859-
if (!opts->context)
2860-
return -ENOMEM;
2861-
}
2862-
if (src->rootcontext) {
2863-
opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
2864-
if (!opts->rootcontext)
2865-
return -ENOMEM;
2866-
}
2867-
if (src->defcontext) {
2868-
opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
2869-
if (!opts->defcontext)
2870-
return -ENOMEM;
2871-
}
2872-
opts->fscontext_sid = src->fscontext_sid;
2873-
opts->context_sid = src->context_sid;
2874-
opts->rootcontext_sid = src->rootcontext_sid;
2875-
opts->defcontext_sid = src->defcontext_sid;
2876-
return 0;
2779+
fc->security = kmemdup(src, sizeof(*src), GFP_KERNEL);
2780+
return fc->security ? 0 : -ENOMEM;
28772781
}
28782782

28792783
static const struct fs_parameter_spec selinux_fs_parameters[] = {

0 commit comments

Comments
 (0)