selinux: kill selinux_sb_get_mnt_opts()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 13 Dec 2018 05:24:36 +0000 (00:24 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Dec 2018 16:48:15 +0000 (11:48 -0500)
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>
security/selinux/hooks.c

index ce0511f..11cf2fe 100644 (file)
@@ -591,105 +591,6 @@ out:
        return rc;
 }
 
-/*
- * This function should allow an FS to ask what it's mount security
- * options were so it can use those later for submounts, displaying
- * mount options, or whatever.
- */
-static int selinux_get_mnt_opts(const struct super_block *sb,
-                               struct security_mnt_opts *opts)
-{
-       int rc = 0, i;
-       struct superblock_security_struct *sbsec = sb->s_security;
-       char *context = NULL;
-       u32 len;
-       char tmp;
-
-       security_init_mnt_opts(opts);
-
-       if (!(sbsec->flags & SE_SBINITIALIZED))
-               return -EINVAL;
-
-       if (!selinux_state.initialized)
-               return -EINVAL;
-
-       /* make sure we always check enough bits to cover the mask */
-       BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
-
-       tmp = sbsec->flags & SE_MNTMASK;
-       /* count the number of mount options for this sb */
-       for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
-               if (tmp & 0x01)
-                       opts->num_mnt_opts++;
-               tmp >>= 1;
-       }
-       /* Check if the Label support flag is set */
-       if (sbsec->flags & SBLABEL_MNT)
-               opts->num_mnt_opts++;
-
-       opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
-       if (!opts->mnt_opts) {
-               rc = -ENOMEM;
-               goto out_free;
-       }
-
-       opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
-       if (!opts->mnt_opts_flags) {
-               rc = -ENOMEM;
-               goto out_free;
-       }
-
-       i = 0;
-       if (sbsec->flags & FSCONTEXT_MNT) {
-               rc = security_sid_to_context(&selinux_state, sbsec->sid,
-                                            &context, &len);
-               if (rc)
-                       goto out_free;
-               opts->mnt_opts[i] = context;
-               opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
-       }
-       if (sbsec->flags & CONTEXT_MNT) {
-               rc = security_sid_to_context(&selinux_state,
-                                            sbsec->mntpoint_sid,
-                                            &context, &len);
-               if (rc)
-                       goto out_free;
-               opts->mnt_opts[i] = context;
-               opts->mnt_opts_flags[i++] = CONTEXT_MNT;
-       }
-       if (sbsec->flags & DEFCONTEXT_MNT) {
-               rc = security_sid_to_context(&selinux_state, sbsec->def_sid,
-                                            &context, &len);
-               if (rc)
-                       goto out_free;
-               opts->mnt_opts[i] = context;
-               opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
-       }
-       if (sbsec->flags & ROOTCONTEXT_MNT) {
-               struct dentry *root = sbsec->sb->s_root;
-               struct inode_security_struct *isec = backing_inode_security(root);
-
-               rc = security_sid_to_context(&selinux_state, isec->sid,
-                                            &context, &len);
-               if (rc)
-                       goto out_free;
-               opts->mnt_opts[i] = context;
-               opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
-       }
-       if (sbsec->flags & SBLABEL_MNT) {
-               opts->mnt_opts[i] = NULL;
-               opts->mnt_opts_flags[i++] = SBLABEL_MNT;
-       }
-
-       BUG_ON(i != opts->num_mnt_opts);
-
-       return 0;
-
-out_free:
-       security_free_mnt_opts(opts);
-       return rc;
-}
-
 static int bad_option(struct superblock_security_struct *sbsec, char flag,
                      u32 old_sid, u32 new_sid)
 {
@@ -1201,70 +1102,73 @@ out_err:
        return rc;
 }
 
-static void selinux_write_opts(struct seq_file *m,
-                              struct security_mnt_opts *opts)
+static int show_sid(struct seq_file *m, u32 sid)
 {
-       int i;
-       char *prefix;
-
-       for (i = 0; i < opts->num_mnt_opts; i++) {
-               char *has_comma;
+       char *context = NULL;
+       u32 len;
+       int rc;
 
-               if (opts->mnt_opts[i])
-                       has_comma = strchr(opts->mnt_opts[i], ',');
-               else
-                       has_comma = NULL;
+       rc = security_sid_to_context(&selinux_state, sid,
+                                            &context, &len);
+       if (!rc) {
+               bool has_comma = context && strchr(context, ',');
 
-               switch (opts->mnt_opts_flags[i]) {
-               case CONTEXT_MNT:
-                       prefix = CONTEXT_STR;
-                       break;
-               case FSCONTEXT_MNT:
-                       prefix = FSCONTEXT_STR;
-                       break;
-               case ROOTCONTEXT_MNT:
-                       prefix = ROOTCONTEXT_STR;
-                       break;
-               case DEFCONTEXT_MNT:
-                       prefix = DEFCONTEXT_STR;
-                       break;
-               case SBLABEL_MNT:
-                       seq_putc(m, ',');
-                       seq_puts(m, LABELSUPP_STR);
-                       continue;
-               default:
-                       BUG();
-                       return;
-               };
-               /* we need a comma before each option */
-               seq_putc(m, ',');
-               seq_puts(m, prefix);
                if (has_comma)
                        seq_putc(m, '\"');
-               seq_escape(m, opts->mnt_opts[i], "\"\n\\");
+               seq_escape(m, context, "\"\n\\");
                if (has_comma)
                        seq_putc(m, '\"');
        }
+       kfree(context);
+       return rc;
 }
 
 static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
 {
-       struct security_mnt_opts opts;
+       struct superblock_security_struct *sbsec = sb->s_security;
        int rc;
 
-       rc = selinux_get_mnt_opts(sb, &opts);
-       if (rc) {
-               /* before policy load we may get EINVAL, don't show anything */
-               if (rc == -EINVAL)
-                       rc = 0;
-               return rc;
-       }
-
-       selinux_write_opts(m, &opts);
+       if (!(sbsec->flags & SE_SBINITIALIZED))
+               return 0;
 
-       security_free_mnt_opts(&opts);
+       if (!selinux_state.initialized)
+               return 0;
 
-       return rc;
+       if (sbsec->flags & FSCONTEXT_MNT) {
+               seq_putc(m, ',');
+               seq_puts(m, FSCONTEXT_STR);
+               rc = show_sid(m, sbsec->sid);
+               if (rc)
+                       return rc;
+       }
+       if (sbsec->flags & CONTEXT_MNT) {
+               seq_putc(m, ',');
+               seq_puts(m, CONTEXT_STR);
+               rc = show_sid(m, sbsec->mntpoint_sid);
+               if (rc)
+                       return rc;
+       }
+       if (sbsec->flags & DEFCONTEXT_MNT) {
+               seq_putc(m, ',');
+               seq_puts(m, DEFCONTEXT_STR);
+               rc = show_sid(m, sbsec->def_sid);
+               if (rc)
+                       return rc;
+       }
+       if (sbsec->flags & ROOTCONTEXT_MNT) {
+               struct dentry *root = sbsec->sb->s_root;
+               struct inode_security_struct *isec = backing_inode_security(root);
+               seq_putc(m, ',');
+               seq_puts(m, ROOTCONTEXT_STR);
+               rc = show_sid(m, isec->sid);
+               if (rc)
+                       return rc;
+       }
+       if (sbsec->flags & SBLABEL_MNT) {
+               seq_putc(m, ',');
+               seq_puts(m, LABELSUPP_STR);
+       }
+       return 0;
 }
 
 static inline u16 inode_mode_to_security_class(umode_t mode)