Btrfs: kfree()ing ERR_PTRs
Subsystems (2)
PATCH 1/1 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.
fs/btrfs/ioctl.c +15 -10
@@ -1702,7 +1702,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | BTRFS_SUBVOL_QGROUP_INHERIT)) { ret = -EOPNOTSUPP ; - goto out; + goto free_args; }if (vol_args->flags &BTRFS_SUBVOL_CREATE_ASYNC )
@@ -1712,27 +1712,31 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,if (vol_args->flags &BTRFS_SUBVOL_QGROUP_INHERIT ) {if (vol_args->size >PAGE_CACHE_SIZE ) { ret = -EINVAL ; - goto out; + goto free_args; } inherit =memdup_user (vol_args->qgroup_inherit, vol_args->size);if (IS_ERR (inherit)) { ret =PTR_ERR (inherit); - goto out; + goto free_args; } } ret =btrfs_ioctl_snap_create_transid (file, vol_args->name, vol_args->fd, subvol, ptr, readonly, inherit); +if (ret) + goto free_inherit; -if (ret =0 && ptr && -copy_to_user (arg + - offsetof(struct btrfs_ioctl_vol_args_v2 , - transid), ptr,sizeof (*ptr))) +if (ptr &©_to_user (arg + + offsetof(struct btrfs_ioctl_vol_args_v2 , + transid), + ptr,sizeof (*ptr))) ret = -EFAULT ; -out: -kfree (vol_args); + +free_inherit:kfree (inherit); +free_args: +kfree (vol_args);return ret; }
@@ -2649,7 +2653,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) vol_args =memdup_user (arg,sizeof (*vol_args));if (IS_ERR (vol_args)) { ret =PTR_ERR (vol_args); - goto out; + goto err_drop; } vol_args->name[BTRFS_PATH_NAME_MAX ] ='\0' ;
@@ -2667,6 +2671,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) out:kfree (vol_args); +err_drop:mnt_drop_write_file (file);return ret; }
Am 04.09.2014 13:09, schrieb Dan Carpenter:
Quoted 44 lines
The "inherit" in
btrfs_ioctl_snap_create_v2()and "vol_args" inbtrfs_ioctl_rm_dev()areERR_PTRsso we can't callkfree()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 <[email protected]>fs/btrfs/ioctl.c +5
-3@@ -1702,7 +1702,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | BTRFS_SUBVOL_QGROUP_INHERIT)) { ret = -EOPNOTSUPP ; - goto out; + goto free_args; }if (vol_args->flags &BTRFS_SUBVOL_CREATE_ASYNC )@@ -1712,27 +1712,31 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,if (vol_args->flags &BTRFS_SUBVOL_QGROUP_INHERIT ) {if (vol_args->size >PAGE_CACHE_SIZE ) { ret = -EINVAL ; - goto out; + goto free_args; } inherit =memdup_user (vol_args->qgroup_inherit, vol_args->size);if (IS_ERR (inherit)) { ret =PTR_ERR (inherit); - goto out; + goto free_args; } } ret =btrfs_ioctl_snap_create_transid (file, vol_args->name, vol_args->fd, subvol, ptr, readonly, inherit); +if (ret) + goto free_inherit;
fs/btrfs/ioctl.c static noinline int btrfs_ioctl_snap_create_v2(struct file *file, · line 1734
Quoted 10 lines
fs/btrfs/ioctl.c +4
-4-if (ret =0 && ptr && -copy_to_user (arg + - offsetof(struct btrfs_ioctl_vol_args_v2 , - transid), ptr,sizeof (*ptr))) +if (ptr &©_to_user (arg + + offsetof(struct btrfs_ioctl_vol_args_v2 , + transid), + ptr,sizeof (*ptr))) ret = -EFAULT ;
this is hard to read.
perhaps it would help to move ptr into the other other
if (ret || !ptr )
goto free_inherit;
both are modified by the call btrfs_ioctl_snap_create_transid().
@Maintainer:
can this really happen ?
More over i would argue that it would nice to rename ptr in to transid_ptr or so, this is what the code is all about and it is not obvious for me.
re,
wh
Quoted 32 lines
fs/btrfs/ioctl.c +6
-4-out: -kfree (vol_args); + +free_inherit:kfree (inherit); +free_args: +kfree (vol_args);return ret; }@@ -2649,7 +2653,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) vol_args =memdup_user (arg,sizeof (*vol_args));if (IS_ERR (vol_args)) { ret =PTR_ERR (vol_args); - goto out; + goto err_drop; } vol_args->name[BTRFS_PATH_NAME_MAX ] ='\0' ;@@ -2667,6 +2671,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) out:kfree (vol_args); +err_drop:mnt_drop_write_file (file);return ret; } --To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 20 lines · walter harms
Quoted 5 lines
fs/btrfs/ioctl.c +2
-0ret =btrfs_ioctl_snap_create_transid (file, vol_args->name, vol_args->fd, subvol, ptr, readonly, inherit); +if (ret) + goto free_inherit;fs/btrfs/ioctl.c static noinline int btrfs_ioctl_snap_create_v2(struct file *file, · line 1734
Quoted 10 lines
fs/btrfs/ioctl.c +4
-4-if (ret =0 && ptr && -copy_to_user (arg + - offsetof(struct btrfs_ioctl_vol_args_v2 , - transid), ptr,sizeof (*ptr))) +if (ptr &©_to_user (arg + + offsetof(struct btrfs_ioctl_vol_args_v2 , + transid), + ptr,sizeof (*ptr))) ret = -EFAULT ;this is hard to read.
perhaps it would help to move ptr into the other other
Quoted 2 lines
if (ret || !ptr )
gotofree_inherit;
I don't think that's an improvement.
Quoted 3 lines
both are modified by the call
btrfs_ioctl_snap_create_transid().
I think you are mixing up ptr and *ptr so that's why you're confused.
regards,
dan carpenter
Quoted 8 lines · Dan Carpenter
The "inherit" in
btrfs_ioctl_snap_create_v2()and "vol_args" inbtrfs_ioctl_rm_dev()areERR_PTRsso we can't callkfree()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.
Thanks Dan, agreed on the unwinding.
-chris