aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <dan.carpenter@oracle.com>2014-09-04 07:09:15 -0400
committerChris Mason <clm@fb.com>2014-09-08 16:56:42 -0400
commitc47ca32d3aadb234f73389a34c97574085bc9eda (patch)
treec53ea33e0067560a26f0122b0b606cc5743b8acc
parentdac5705cad20070a70bb028ca52e1f0bc157b42d (diff)
Btrfs: kfree()ing ERR_PTRs
The "inherit" in btrfs_ioctl_snap_create_v2() and "vol_args" in btrfs_ioctl_rm_dev() are ERR_PTRs so we can't call kfree() on them. These kind of bugs are "One Err Bugs" where there is just one error label that does everything. I could set the "inherit = NULL" and keep the single out label but it ends up being more complicated that way. It makes the code simpler to re-order the unwind so it's in the mirror order of the allocation and introduce some new error labels. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/ioctl.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index a018ea484d39..8a8e29878c34 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1703,7 +1703,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
1703 ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | 1703 ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
1704 BTRFS_SUBVOL_QGROUP_INHERIT)) { 1704 BTRFS_SUBVOL_QGROUP_INHERIT)) {
1705 ret = -EOPNOTSUPP; 1705 ret = -EOPNOTSUPP;
1706 goto out; 1706 goto free_args;
1707 } 1707 }
1708 1708
1709 if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC) 1709 if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
@@ -1713,27 +1713,31 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
1713 if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { 1713 if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
1714 if (vol_args->size > PAGE_CACHE_SIZE) { 1714 if (vol_args->size > PAGE_CACHE_SIZE) {
1715 ret = -EINVAL; 1715 ret = -EINVAL;
1716 goto out; 1716 goto free_args;
1717 } 1717 }
1718 inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size); 1718 inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size);
1719 if (IS_ERR(inherit)) { 1719 if (IS_ERR(inherit)) {
1720 ret = PTR_ERR(inherit); 1720 ret = PTR_ERR(inherit);
1721 goto out; 1721 goto free_args;
1722 } 1722 }
1723 } 1723 }
1724 1724
1725 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, 1725 ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
1726 vol_args->fd, subvol, ptr, 1726 vol_args->fd, subvol, ptr,
1727 readonly, inherit); 1727 readonly, inherit);
1728 if (ret)
1729 goto free_inherit;
1728 1730
1729 if (ret == 0 && ptr && 1731 if (ptr && copy_to_user(arg +
1730 copy_to_user(arg + 1732 offsetof(struct btrfs_ioctl_vol_args_v2,
1731 offsetof(struct btrfs_ioctl_vol_args_v2, 1733 transid),
1732 transid), ptr, sizeof(*ptr))) 1734 ptr, sizeof(*ptr)))
1733 ret = -EFAULT; 1735 ret = -EFAULT;
1734out: 1736
1735 kfree(vol_args); 1737free_inherit:
1736 kfree(inherit); 1738 kfree(inherit);
1739free_args:
1740 kfree(vol_args);
1737 return ret; 1741 return ret;
1738} 1742}
1739 1743
@@ -2653,7 +2657,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
2653 vol_args = memdup_user(arg, sizeof(*vol_args)); 2657 vol_args = memdup_user(arg, sizeof(*vol_args));
2654 if (IS_ERR(vol_args)) { 2658 if (IS_ERR(vol_args)) {
2655 ret = PTR_ERR(vol_args); 2659 ret = PTR_ERR(vol_args);
2656 goto out; 2660 goto err_drop;
2657 } 2661 }
2658 2662
2659 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; 2663 vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
@@ -2671,6 +2675,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
2671 2675
2672out: 2676out:
2673 kfree(vol_args); 2677 kfree(vol_args);
2678err_drop:
2674 mnt_drop_write_file(file); 2679 mnt_drop_write_file(file);
2675 return ret; 2680 return ret;
2676} 2681}