platform/x86: think-lmi: Fix reference leak
authorArmin Wolf <W_Armin@gmx.de>
Mon, 25 Sep 2023 14:28:18 +0000 (16:28 +0200)
committerHans de Goede <hdegoede@redhat.com>
Wed, 4 Oct 2023 09:52:17 +0000 (11:52 +0200)
If a duplicate attribute is found using kset_find_obj(), a reference
to that attribute is returned which needs to be disposed accordingly
using kobject_put(). Move the setting name validation into a separate
function to allow for this change without having to duplicate the
cleanup code for this setting.
As a side note, a very similar bug was fixed in
commit 7295a996fdab ("platform/x86: dell-sysman: Fix reference leak"),
so it seems that the bug was copied from that driver.

Compile-tested only.

Fixes: 1bcad8e510b2 ("platform/x86: think-lmi: Fix issues with duplicate attributes")
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20230925142819.74525-2-W_Armin@gmx.de
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
drivers/platform/x86/think-lmi.c

index 7934688..aee8697 100644 (file)
@@ -1248,6 +1248,24 @@ static void tlmi_release_attr(void)
        kset_unregister(tlmi_priv.authentication_kset);
 }
 
+static int tlmi_validate_setting_name(struct kset *attribute_kset, char *name)
+{
+       struct kobject *duplicate;
+
+       if (!strcmp(name, "Reserved"))
+               return -EINVAL;
+
+       duplicate = kset_find_obj(attribute_kset, name);
+       if (duplicate) {
+               pr_debug("Duplicate attribute name found - %s\n", name);
+               /* kset_find_obj() returns a reference */
+               kobject_put(duplicate);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 static int tlmi_sysfs_init(void)
 {
        int i, ret;
@@ -1276,10 +1294,8 @@ static int tlmi_sysfs_init(void)
                        continue;
 
                /* check for duplicate or reserved values */
-               if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) ||
-                   !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) {
-                       pr_debug("duplicate or reserved attribute name found - %s\n",
-                               tlmi_priv.setting[i]->display_name);
+               if (tlmi_validate_setting_name(tlmi_priv.attribute_kset,
+                                              tlmi_priv.setting[i]->display_name) < 0) {
                        kfree(tlmi_priv.setting[i]->possible_values);
                        kfree(tlmi_priv.setting[i]);
                        tlmi_priv.setting[i] = NULL;