btrfs: sanitize security_mnt_opts use
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>
This commit is contained in:
parent
8d64124a6a
commit
a65001e8a4
|
@ -1100,9 +1100,6 @@ struct btrfs_fs_info {
|
||||||
struct mutex unused_bg_unpin_mutex;
|
struct mutex unused_bg_unpin_mutex;
|
||||||
struct mutex delete_unused_bgs_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)
|
* Chunks that can't be freed yet (under a trim/discard operation)
|
||||||
* and will be latter freed. Protected by fs_info->chunk_mutex.
|
* 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->free_space_root);
|
||||||
kfree(fs_info->super_copy);
|
kfree(fs_info->super_copy);
|
||||||
kfree(fs_info->super_for_commit);
|
kfree(fs_info->super_for_commit);
|
||||||
security_free_mnt_opts(&fs_info->security_opts);
|
|
||||||
kvfree(fs_info);
|
kvfree(fs_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1458,43 +1458,6 @@ out:
|
||||||
return root;
|
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.
|
* 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);
|
security_init_mnt_opts(&new_sec_opts);
|
||||||
if (data) {
|
if (data) {
|
||||||
error = parse_security_options(data, &new_sec_opts);
|
error = security_sb_eat_lsm_opts(data, &new_sec_opts);
|
||||||
if (error)
|
if (error)
|
||||||
return ERR_PTR(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_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL);
|
||||||
fs_info->super_for_commit = 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) {
|
if (!fs_info->super_copy || !fs_info->super_for_commit) {
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
goto error_fs_info;
|
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;
|
btrfs_sb(s)->bdev_holder = fs_type;
|
||||||
error = btrfs_fill_super(s, fs_devices, data);
|
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) {
|
if (error) {
|
||||||
deactivate_locked_super(s);
|
deactivate_locked_super(s);
|
||||||
goto error_sec_opts;
|
return ERR_PTR(error);
|
||||||
}
|
|
||||||
|
|
||||||
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 dget(s->s_root);
|
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;
|
struct security_mnt_opts new_sec_opts;
|
||||||
|
|
||||||
security_init_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)
|
if (ret)
|
||||||
goto restore;
|
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);
|
ret = btrfs_parse_options(fs_info, data, *flags);
|
||||||
|
|
|
@ -404,6 +404,7 @@ int security_sb_remount(struct super_block *sb,
|
||||||
{
|
{
|
||||||
return call_int_hook(sb_remount, 0, sb, opts);
|
return call_int_hook(sb_remount, 0, sb, opts);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(security_sb_remount);
|
||||||
|
|
||||||
int security_sb_kern_mount(struct super_block *sb)
|
int security_sb_kern_mount(struct super_block *sb)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue