btrfs: factor out validation of btrfs_ioctl_vol_args::name
[linux-2.6-block.git] / fs / btrfs / ioctl.c
index eb736281eb639fa12536d84b7b845a305e797a85..81d3117954037ac737fca02194de1d8d3d36949d 100644 (file)
@@ -227,6 +227,13 @@ static int check_fsflags_compatible(struct btrfs_fs_info *fs_info,
        return 0;
 }
 
+int btrfs_check_ioctl_vol_args_path(const struct btrfs_ioctl_vol_args *vol_args)
+{
+       if (memchr(vol_args->name, 0, sizeof(vol_args->name)) == NULL)
+               return -ENAMETOOLONG;
+       return 0;
+}
+
 /*
  * Set flags/xflags from the internal inode flags. The remaining items of
  * fsxattr are zeroed.
@@ -1126,7 +1133,10 @@ static noinline int btrfs_ioctl_resize(struct file *file,
                ret = PTR_ERR(vol_args);
                goto out_drop;
        }
-       vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
+       ret = btrfs_check_ioctl_vol_args_path(vol_args);
+       if (ret < 0)
+               goto out_free;
+
        sizestr = vol_args->name;
        cancel = (strcmp("cancel", sizestr) == 0);
        ret = exclop_start_or_cancel_reloc(fs_info, BTRFS_EXCLOP_RESIZE, cancel);
@@ -1326,12 +1336,15 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
        vol_args = memdup_user(arg, sizeof(*vol_args));
        if (IS_ERR(vol_args))
                return PTR_ERR(vol_args);
-       vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
+       ret = btrfs_check_ioctl_vol_args_path(vol_args);
+       if (ret < 0)
+               goto out;
 
        ret = __btrfs_ioctl_snap_create(file, file_mnt_idmap(file),
                                        vol_args->name, vol_args->fd, subvol,
                                        false, NULL);
 
+out:
        kfree(vol_args);
        return ret;
 }
@@ -2464,7 +2477,10 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
                if (IS_ERR(vol_args))
                        return PTR_ERR(vol_args);
 
-               vol_args->name[BTRFS_PATH_NAME_MAX] = 0;
+               err = btrfs_check_ioctl_vol_args_path(vol_args);
+               if (err < 0)
+                       goto out;
+
                subvol_name = vol_args->name;
 
                err = mnt_want_write_file(file);
@@ -2675,12 +2691,16 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
                goto out;
        }
 
-       vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
+       ret = btrfs_check_ioctl_vol_args_path(vol_args);
+       if (ret < 0)
+               goto out_free;
+
        ret = btrfs_init_new_device(fs_info, vol_args->name);
 
        if (!ret)
                btrfs_info(fs_info, "disk added %s", vol_args->name);
 
+out_free:
        kfree(vol_args);
 out:
        if (restore_op)
@@ -2772,7 +2792,10 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        if (IS_ERR(vol_args))
                return PTR_ERR(vol_args);
 
-       vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
+       ret = btrfs_check_ioctl_vol_args_path(vol_args);
+       if (ret < 0)
+               goto out_free;
+
        if (!strcmp("cancel", vol_args->name)) {
                cancel = true;
        } else {
@@ -2799,6 +2822,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
                bdev_release(bdev_handle);
 out:
        btrfs_put_dev_args_from_path(&args);
+out_free:
        kfree(vol_args);
        return ret;
 }