btrfs: sanitize security_mnt_opts use
authorAl Viro <viro@zeniv.linux.org.uk>
Mon, 10 Dec 2018 22:19:21 +0000 (17:19 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 Dec 2018 16:47:08 +0000 (11:47 -0500)
1) keeping a copy in btrfs_fs_info is completely pointless - we never
use it for anything.  Getting rid of that allows for simpler calling
conventions for setup_security_options() (caller is responsible for
freeing mnt_opts in all cases).

2) on remount we want to use ->sb_remount(), not ->sb_set_mnt_opts(),
same as we would if not for FS_BINARY_MOUNTDATA.  Behaviours *are*
close (in fact, selinux sb_set_mnt_opts() ought to punt to
sb_remount() in "already initialized" case), but let's handle
that uniformly.  And the only reason why the original btrfs changes
didn't go for security_sb_remount() in btrfs_remount() case is that
it hadn't been exported.  Let's export it for a while - it'll be
going away soon anyway.

Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/btrfs/ctree.h
fs/btrfs/super.c
security/security.c

index 8095352..f7ec833 100644 (file)
@@ -1100,9 +1100,6 @@ struct btrfs_fs_info {
        struct mutex unused_bg_unpin_mutex;
        struct mutex delete_unused_bgs_mutex;
 
-       /* For btrfs to record security options */
-       struct security_mnt_opts security_opts;
-
        /*
         * Chunks that can't be freed yet (under a trim/discard operation)
         * and will be latter freed. Protected by fs_info->chunk_mutex.
@@ -2959,7 +2956,6 @@ static inline void free_fs_info(struct btrfs_fs_info *fs_info)
        kfree(fs_info->free_space_root);
        kfree(fs_info->super_copy);
        kfree(fs_info->super_for_commit);
-       security_free_mnt_opts(&fs_info->security_opts);
        kvfree(fs_info);
 }
 
index 6fc8e96..3b04e77 100644 (file)
@@ -1458,43 +1458,6 @@ out:
        return root;
 }
 
-static int parse_security_options(char *orig_opts,
-                                 struct security_mnt_opts *sec_opts)
-{
-       return security_sb_eat_lsm_opts(orig_opts, sec_opts);
-}
-
-static int setup_security_options(struct btrfs_fs_info *fs_info,
-                                 struct super_block *sb,
-                                 struct security_mnt_opts *sec_opts)
-{
-       int ret = 0;
-
-       /*
-        * Call security_sb_set_mnt_opts() to check whether new sec_opts
-        * is valid.
-        */
-       ret = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL);
-       if (ret)
-               return ret;
-
-#ifdef CONFIG_SECURITY
-       if (!fs_info->security_opts.num_mnt_opts) {
-               /* first time security setup, copy sec_opts to fs_info */
-               memcpy(&fs_info->security_opts, sec_opts, sizeof(*sec_opts));
-       } else {
-               /*
-                * Since SELinux (the only one supporting security_mnt_opts)
-                * does NOT support changing context during remount/mount of
-                * the same sb, this must be the same or part of the same
-                * security options, just free it.
-                */
-               security_free_mnt_opts(sec_opts);
-       }
-#endif
-       return ret;
-}
-
 /*
  * Find a superblock for the given device / mount point.
  *
@@ -1518,7 +1481,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
 
        security_init_mnt_opts(&new_sec_opts);
        if (data) {
-               error = parse_security_options(data, &new_sec_opts);
+               error = security_sb_eat_lsm_opts(data, &new_sec_opts);
                if (error)
                        return ERR_PTR(error);
        }
@@ -1537,7 +1500,6 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
 
        fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
        fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
-       security_init_mnt_opts(&fs_info->security_opts);
        if (!fs_info->super_copy || !fs_info->super_for_commit) {
                error = -ENOMEM;
                goto error_fs_info;
@@ -1588,16 +1550,12 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type,
                btrfs_sb(s)->bdev_holder = fs_type;
                error = btrfs_fill_super(s, fs_devices, data);
        }
+       if (!error)
+               error = security_sb_set_mnt_opts(s, &new_sec_opts, 0, NULL);
+       security_free_mnt_opts(&new_sec_opts);
        if (error) {
                deactivate_locked_super(s);
-               goto error_sec_opts;
-       }
-
-       fs_info = btrfs_sb(s);
-       error = setup_security_options(fs_info, s, &new_sec_opts);
-       if (error) {
-               deactivate_locked_super(s);
-               goto error_sec_opts;
+               return ERR_PTR(error);
        }
 
        return dget(s->s_root);
@@ -1769,15 +1727,12 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                struct security_mnt_opts new_sec_opts;
 
                security_init_mnt_opts(&new_sec_opts);
-               ret = parse_security_options(data, &new_sec_opts);
+               ret = security_sb_eat_lsm_opts(data, &new_sec_opts);
+               if (!ret)
+                       ret = security_sb_remount(sb, &new_sec_opts);
+               security_free_mnt_opts(&new_sec_opts);
                if (ret)
                        goto restore;
-               ret = setup_security_options(fs_info, sb,
-                                            &new_sec_opts);
-               if (ret) {
-                       security_free_mnt_opts(&new_sec_opts);
-                       goto restore;
-               }
        }
 
        ret = btrfs_parse_options(fs_info, data, *flags);
index afb0564..3d8b729 100644 (file)
@@ -404,6 +404,7 @@ int security_sb_remount(struct super_block *sb,
 {
        return call_int_hook(sb_remount, 0, sb, opts);
 }
+EXPORT_SYMBOL(security_sb_remount);
 
 int security_sb_kern_mount(struct super_block *sb)
 {