cpuidle: Fix kobject memory leaks in error paths
authorAnel Orazgaliyeva <anelkz@amazon.de>
Mon, 6 Sep 2021 18:34:40 +0000 (18:34 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:16:29 +0000 (19:16 +0100)
[ Upstream commit e5f5a66c9aa9c331da5527c2e3fd9394e7091e01 ]

Commit c343bf1ba5ef ("cpuidle: Fix three reference count leaks")
fixes the cleanup of kobjects; however, it removes kfree() calls
altogether, leading to memory leaks.

Fix those and also defer the initialization of dev->kobj_dev until
after the error check, so that we do not end up with a dangling
pointer.

Fixes: c343bf1ba5ef ("cpuidle: Fix three reference count leaks")
Signed-off-by: Anel Orazgaliyeva <anelkz@amazon.de>
Suggested-by: Aman Priyadarshi <apeureka@amazon.de>
[ rjw: Subject edits ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/cpuidle/sysfs.c

index 53ec958..469e185 100644 (file)
@@ -488,6 +488,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
                                           &kdev->kobj, "state%d", i);
                if (ret) {
                        kobject_put(&kobj->kobj);
+                       kfree(kobj);
                        goto error_state;
                }
                cpuidle_add_s2idle_attr_group(kobj);
@@ -619,6 +620,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
                                   &kdev->kobj, "driver");
        if (ret) {
                kobject_put(&kdrv->kobj);
+               kfree(kdrv);
                return ret;
        }
 
@@ -705,7 +707,6 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
        if (!kdev)
                return -ENOMEM;
        kdev->dev = dev;
-       dev->kobj_dev = kdev;
 
        init_completion(&kdev->kobj_unregister);
 
@@ -713,9 +714,11 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev)
                                   "cpuidle");
        if (error) {
                kobject_put(&kdev->kobj);
+               kfree(kdev);
                return error;
        }
 
+       dev->kobj_dev = kdev;
        kobject_uevent(&kdev->kobj, KOBJ_ADD);
 
        return 0;