| From e32773357d5cc271b1d23550b3ed026eb5c2a468 Mon Sep 17 00:00:00 2001 |
| From: "Tobin C. Harding" <tobin@kernel.org> |
| Date: Mon, 13 May 2019 13:39:12 +1000 |
| Subject: btrfs: sysfs: don't leak memory when failing add fsid |
| |
| From: Tobin C. Harding <tobin@kernel.org> |
| |
| commit e32773357d5cc271b1d23550b3ed026eb5c2a468 upstream. |
| |
| A failed call to kobject_init_and_add() must be followed by a call to |
| kobject_put(). Currently in the error path when adding fs_devices we |
| are missing this call. This could be fixed by calling |
| btrfs_sysfs_remove_fsid() if btrfs_sysfs_add_fsid() returns an error or |
| by adding a call to kobject_put() directly in btrfs_sysfs_add_fsid(). |
| Here we choose the second option because it prevents the slightly |
| unusual error path handling requirements of kobject from leaking out |
| into btrfs functions. |
| |
| Add a call to kobject_put() in the error path of kobject_add_and_init(). |
| This causes the release method to be called if kobject_init_and_add() |
| fails. open_tree() is the function that calls btrfs_sysfs_add_fsid() |
| and the error code in this function is already written with the |
| assumption that the release method is called during the error path of |
| open_tree() (as seen by the call to btrfs_sysfs_remove_fsid() under the |
| fail_fsdev_sysfs label). |
| |
| Cc: stable@vger.kernel.org # v4.4+ |
| Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Tobin C. Harding <tobin@kernel.org> |
| Reviewed-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: David Sterba <dsterba@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/btrfs/sysfs.c | 7 ++++++- |
| 1 file changed, 6 insertions(+), 1 deletion(-) |
| |
| --- a/fs/btrfs/sysfs.c |
| +++ b/fs/btrfs/sysfs.c |
| @@ -825,7 +825,12 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs |
| fs_devs->fsid_kobj.kset = btrfs_kset; |
| error = kobject_init_and_add(&fs_devs->fsid_kobj, |
| &btrfs_ktype, parent, "%pU", fs_devs->fsid); |
| - return error; |
| + if (error) { |
| + kobject_put(&fs_devs->fsid_kobj); |
| + return error; |
| + } |
| + |
| + return 0; |
| } |
| |
| int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) |