summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-12-13 00:24:36 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2018-12-21 11:48:15 -0500
commite3489f8974e178d723259a842a1e61708dd7dc1e (patch)
tree9fb393250ec2446ded96fa641630ed0dfeb68dfe /security
parent5b4002391153acebce2557af318bbdc17e235134 (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.c198
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 */
599static 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
688out_free:
689 security_free_mnt_opts(opts);
690 return rc;
691}
692
693static int bad_option(struct superblock_security_struct *sbsec, char flag, 594static 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
1204static void selinux_write_opts(struct seq_file *m, 1105static 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
1250static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb) 1126static 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
1270static inline u16 inode_mode_to_security_class(umode_t mode) 1174static inline u16 inode_mode_to_security_class(umode_t mode)