btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl

The problem is we're copying "inherit" from user space but we don't
necessarily know that we're copying enough data for a 64 byte
struct.  Then the next problem is that 'inherit' has a variable size
array at the end, and we have to verify that array is the size we
expected.

Fixes: 6f72c7e20d ("Btrfs: add qgroup inheritance")
CC: stable@vger.kernel.org # 4.4+
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Dan Carpenter 2021-02-17 09:04:34 +03:00 committed by David Sterba
parent 4f6a49de64
commit 5011c5a663

View File

@ -1935,7 +1935,10 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
readonly = true;
if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
if (vol_args->size > PAGE_SIZE) {
u64 nums;
if (vol_args->size < sizeof(*inherit) ||
vol_args->size > PAGE_SIZE) {
ret = -EINVAL;
goto free_args;
}
@ -1944,6 +1947,20 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
ret = PTR_ERR(inherit);
goto free_args;
}
if (inherit->num_qgroups > PAGE_SIZE ||
inherit->num_ref_copies > PAGE_SIZE ||
inherit->num_excl_copies > PAGE_SIZE) {
ret = -EINVAL;
goto free_inherit;
}
nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
2 * inherit->num_excl_copies;
if (vol_args->size != struct_size(inherit, qgroups, nums)) {
ret = -EINVAL;
goto free_inherit;
}
}
ret = __btrfs_ioctl_snap_create(file, vol_args->name, vol_args->fd,