diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-13 00:24:36 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-12-21 11:48:15 -0500 |
commit | e3489f8974e178d723259a842a1e61708dd7dc1e (patch) | |
tree | 9fb393250ec2446ded96fa641630ed0dfeb68dfe /security | |
parent | 5b4002391153acebce2557af318bbdc17e235134 (diff) |
selinux: kill selinux_sb_get_mnt_opts()
it's much easier to just do the right thing in ->sb_show_options(),
without bothering with allocating and populating arrays, etc.
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/hooks.c | 198 |
1 files changed, 51 insertions, 147 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ce0511f024e0..11cf2feb27b3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -591,105 +591,6 @@ out: | |||
591 | return rc; | 591 | return rc; |
592 | } | 592 | } |
593 | 593 | ||
594 | /* | ||
595 | * This function should allow an FS to ask what it's mount security | ||
596 | * options were so it can use those later for submounts, displaying | ||
597 | * mount options, or whatever. | ||
598 | */ | ||
599 | static int selinux_get_mnt_opts(const struct super_block *sb, | ||
600 | struct security_mnt_opts *opts) | ||
601 | { | ||
602 | int rc = 0, i; | ||
603 | struct superblock_security_struct *sbsec = sb->s_security; | ||
604 | char *context = NULL; | ||
605 | u32 len; | ||
606 | char tmp; | ||
607 | |||
608 | security_init_mnt_opts(opts); | ||
609 | |||
610 | if (!(sbsec->flags & SE_SBINITIALIZED)) | ||
611 | return -EINVAL; | ||
612 | |||
613 | if (!selinux_state.initialized) | ||
614 | return -EINVAL; | ||
615 | |||
616 | /* make sure we always check enough bits to cover the mask */ | ||
617 | BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS)); | ||
618 | |||
619 | tmp = sbsec->flags & SE_MNTMASK; | ||
620 | /* count the number of mount options for this sb */ | ||
621 | for (i = 0; i < NUM_SEL_MNT_OPTS; i++) { | ||
622 | if (tmp & 0x01) | ||
623 | opts->num_mnt_opts++; | ||
624 | tmp >>= 1; | ||
625 | } | ||
626 | /* Check if the Label support flag is set */ | ||
627 | if (sbsec->flags & SBLABEL_MNT) | ||
628 | opts->num_mnt_opts++; | ||
629 | |||
630 | opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC); | ||
631 | if (!opts->mnt_opts) { | ||
632 | rc = -ENOMEM; | ||
633 | goto out_free; | ||
634 | } | ||
635 | |||
636 | opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC); | ||
637 | if (!opts->mnt_opts_flags) { | ||
638 | rc = -ENOMEM; | ||
639 | goto out_free; | ||
640 | } | ||
641 | |||
642 | i = 0; | ||
643 | if (sbsec->flags & FSCONTEXT_MNT) { | ||
644 | rc = security_sid_to_context(&selinux_state, sbsec->sid, | ||
645 | &context, &len); | ||
646 | if (rc) | ||
647 | goto out_free; | ||
648 | opts->mnt_opts[i] = context; | ||
649 | opts->mnt_opts_flags[i++] = FSCONTEXT_MNT; | ||
650 | } | ||
651 | if (sbsec->flags & CONTEXT_MNT) { | ||
652 | rc = security_sid_to_context(&selinux_state, | ||
653 | sbsec->mntpoint_sid, | ||
654 | &context, &len); | ||
655 | if (rc) | ||
656 | goto out_free; | ||
657 | opts->mnt_opts[i] = context; | ||
658 | opts->mnt_opts_flags[i++] = CONTEXT_MNT; | ||
659 | } | ||
660 | if (sbsec->flags & DEFCONTEXT_MNT) { | ||
661 | rc = security_sid_to_context(&selinux_state, sbsec->def_sid, | ||
662 | &context, &len); | ||
663 | if (rc) | ||
664 | goto out_free; | ||
665 | opts->mnt_opts[i] = context; | ||
666 | opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT; | ||
667 | } | ||
668 | if (sbsec->flags & ROOTCONTEXT_MNT) { | ||
669 | struct dentry *root = sbsec->sb->s_root; | ||
670 | struct inode_security_struct *isec = backing_inode_security(root); | ||
671 | |||
672 | rc = security_sid_to_context(&selinux_state, isec->sid, | ||
673 | &context, &len); | ||
674 | if (rc) | ||
675 | goto out_free; | ||
676 | opts->mnt_opts[i] = context; | ||
677 | opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT; | ||
678 | } | ||
679 | if (sbsec->flags & SBLABEL_MNT) { | ||
680 | opts->mnt_opts[i] = NULL; | ||
681 | opts->mnt_opts_flags[i++] = SBLABEL_MNT; | ||
682 | } | ||
683 | |||
684 | BUG_ON(i != opts->num_mnt_opts); | ||
685 | |||
686 | return 0; | ||
687 | |||
688 | out_free: | ||
689 | security_free_mnt_opts(opts); | ||
690 | return rc; | ||
691 | } | ||
692 | |||
693 | static int bad_option(struct superblock_security_struct *sbsec, char flag, | 594 | static int bad_option(struct superblock_security_struct *sbsec, char flag, |
694 | u32 old_sid, u32 new_sid) | 595 | u32 old_sid, u32 new_sid) |
695 | { | 596 | { |
@@ -1201,70 +1102,73 @@ out_err: | |||
1201 | return rc; | 1102 | return rc; |
1202 | } | 1103 | } |
1203 | 1104 | ||
1204 | static void selinux_write_opts(struct seq_file *m, | 1105 | static int show_sid(struct seq_file *m, u32 sid) |
1205 | struct security_mnt_opts *opts) | ||
1206 | { | 1106 | { |
1207 | int i; | 1107 | char *context = NULL; |
1208 | char *prefix; | 1108 | u32 len; |
1209 | 1109 | int rc; | |
1210 | for (i = 0; i < opts->num_mnt_opts; i++) { | ||
1211 | char *has_comma; | ||
1212 | 1110 | ||
1213 | if (opts->mnt_opts[i]) | 1111 | rc = security_sid_to_context(&selinux_state, sid, |
1214 | has_comma = strchr(opts->mnt_opts[i], ','); | 1112 | &context, &len); |
1215 | else | 1113 | if (!rc) { |
1216 | has_comma = NULL; | 1114 | bool has_comma = context && strchr(context, ','); |
1217 | 1115 | ||
1218 | switch (opts->mnt_opts_flags[i]) { | ||
1219 | case CONTEXT_MNT: | ||
1220 | prefix = CONTEXT_STR; | ||
1221 | break; | ||
1222 | case FSCONTEXT_MNT: | ||
1223 | prefix = FSCONTEXT_STR; | ||
1224 | break; | ||
1225 | case ROOTCONTEXT_MNT: | ||
1226 | prefix = ROOTCONTEXT_STR; | ||
1227 | break; | ||
1228 | case DEFCONTEXT_MNT: | ||
1229 | prefix = DEFCONTEXT_STR; | ||
1230 | break; | ||
1231 | case SBLABEL_MNT: | ||
1232 | seq_putc(m, ','); | ||
1233 | seq_puts(m, LABELSUPP_STR); | ||
1234 | continue; | ||
1235 | default: | ||
1236 | BUG(); | ||
1237 | return; | ||
1238 | }; | ||
1239 | /* we need a comma before each option */ | ||
1240 | seq_putc(m, ','); | ||
1241 | seq_puts(m, prefix); | ||
1242 | if (has_comma) | 1116 | if (has_comma) |
1243 | seq_putc(m, '\"'); | 1117 | seq_putc(m, '\"'); |
1244 | seq_escape(m, opts->mnt_opts[i], "\"\n\\"); | 1118 | seq_escape(m, context, "\"\n\\"); |
1245 | if (has_comma) | 1119 | if (has_comma) |
1246 | seq_putc(m, '\"'); | 1120 | seq_putc(m, '\"'); |
1247 | } | 1121 | } |
1122 | kfree(context); | ||
1123 | return rc; | ||
1248 | } | 1124 | } |
1249 | 1125 | ||
1250 | static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) | 1126 | static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) |
1251 | { | 1127 | { |
1252 | struct security_mnt_opts opts; | 1128 | struct superblock_security_struct *sbsec = sb->s_security; |
1253 | int rc; | 1129 | int rc; |
1254 | 1130 | ||
1255 | rc = selinux_get_mnt_opts(sb, &opts); | 1131 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
1256 | if (rc) { | 1132 | return 0; |
1257 | /* before policy load we may get EINVAL, don't show anything */ | ||
1258 | if (rc == -EINVAL) | ||
1259 | rc = 0; | ||
1260 | return rc; | ||
1261 | } | ||
1262 | |||
1263 | selinux_write_opts(m, &opts); | ||
1264 | 1133 | ||
1265 | security_free_mnt_opts(&opts); | 1134 | if (!selinux_state.initialized) |
1135 | return 0; | ||
1266 | 1136 | ||
1267 | return rc; | 1137 | if (sbsec->flags & FSCONTEXT_MNT) { |
1138 | seq_putc(m, ','); | ||
1139 | seq_puts(m, FSCONTEXT_STR); | ||
1140 | rc = show_sid(m, sbsec->sid); | ||
1141 | if (rc) | ||
1142 | return rc; | ||
1143 | } | ||
1144 | if (sbsec->flags & CONTEXT_MNT) { | ||
1145 | seq_putc(m, ','); | ||
1146 | seq_puts(m, CONTEXT_STR); | ||
1147 | rc = show_sid(m, sbsec->mntpoint_sid); | ||
1148 | if (rc) | ||
1149 | return rc; | ||
1150 | } | ||
1151 | if (sbsec->flags & DEFCONTEXT_MNT) { | ||
1152 | seq_putc(m, ','); | ||
1153 | seq_puts(m, DEFCONTEXT_STR); | ||
1154 | rc = show_sid(m, sbsec->def_sid); | ||
1155 | if (rc) | ||
1156 | return rc; | ||
1157 | } | ||
1158 | if (sbsec->flags & ROOTCONTEXT_MNT) { | ||
1159 | struct dentry *root = sbsec->sb->s_root; | ||
1160 | struct inode_security_struct *isec = backing_inode_security(root); | ||
1161 | seq_putc(m, ','); | ||
1162 | seq_puts(m, ROOTCONTEXT_STR); | ||
1163 | rc = show_sid(m, isec->sid); | ||
1164 | if (rc) | ||
1165 | return rc; | ||
1166 | } | ||
1167 | if (sbsec->flags & SBLABEL_MNT) { | ||
1168 | seq_putc(m, ','); | ||
1169 | seq_puts(m, LABELSUPP_STR); | ||
1170 | } | ||
1171 | return 0; | ||
1268 | } | 1172 | } |
1269 | 1173 | ||
1270 | static inline u16 inode_mode_to_security_class(umode_t mode) | 1174 | static inline u16 inode_mode_to_security_class(umode_t mode) |