diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-12-18 16:25:45 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | 4aec2b52327b3a3a20faa3f1af3102c0d97c7c92 (patch) | |
tree | f17d84355d64dd42c17462069b00f271f920e4a0 /fs/btrfs/inode.c | |
parent | 6da6abae027e2dbc59bca5f4168b0760f25068c7 (diff) |
kmalloc a few large stack objects in the btrfs_ioctl path
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6a7d9160df2..1e725a48467 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2302,40 +2302,64 @@ out_unlock: static int btrfs_ioctl_snap_create(struct btrfs_root *root, void __user *arg) { - struct btrfs_ioctl_vol_args vol_args; + struct btrfs_ioctl_vol_args *vol_args; struct btrfs_dir_item *di; struct btrfs_path *path; - int namelen; u64 root_dirid; + int namelen; + int ret; - if (copy_from_user(&vol_args, arg, sizeof(vol_args))) - return -EFAULT; + vol_args = kmalloc(sizeof(*vol_args), GFP_NOFS); - namelen = strlen(vol_args.name); - if (namelen > BTRFS_VOL_NAME_MAX) - return -EINVAL; - if (strchr(vol_args.name, '/')) - return -EINVAL; + if (!vol_args) + return -ENOMEM; + + if (copy_from_user(vol_args, arg, sizeof(*vol_args))) { + ret = -EFAULT; + goto out; + } + + namelen = strlen(vol_args->name); + if (namelen > BTRFS_VOL_NAME_MAX) { + ret = -EINVAL; + goto out; + } + if (strchr(vol_args->name, '/')) { + ret = -EINVAL; + goto out; + } path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out; + } root_dirid = root->fs_info->sb->s_root->d_inode->i_ino, mutex_lock(&root->fs_info->fs_mutex); di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, path, root_dirid, - vol_args.name, namelen, 0); + vol_args->name, namelen, 0); mutex_unlock(&root->fs_info->fs_mutex); btrfs_free_path(path); - if (di && !IS_ERR(di)) - return -EEXIST; - if (IS_ERR(di)) - return PTR_ERR(di); + + if (di && !IS_ERR(di)) { + ret = -EEXIST; + goto out; + } + + if (IS_ERR(di)) { + ret = PTR_ERR(di); + goto out; + } if (root == root->fs_info->tree_root) - return create_subvol(root, vol_args.name, namelen); - return create_snapshot(root, vol_args.name, namelen); + ret = create_subvol(root, vol_args->name, namelen); + else + ret = create_snapshot(root, vol_args->name, namelen); +out: + kfree(vol_args); + return ret; } static int btrfs_ioctl_defrag(struct file *file) |