]> git.hungrycats.org Git - linux/commitdiff
driver core: Fix error handling in driver API device_rename()
authorZijun Hu <quic_zijuhu@quicinc.com>
Mon, 22 Jul 2024 14:48:10 +0000 (22:48 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 4 Oct 2024 14:33:17 +0000 (16:33 +0200)
[ Upstream commit 6d8249ac29bc23260dfa9747eb398ce76012d73c ]

For class-device, device_rename() failure maybe cause unexpected link name
within its class folder as explained below:

/sys/class/.../old_name -> /sys/devices/.../old_name
device_rename(..., new_name) and failed
/sys/class/.../new_name -> /sys/devices/.../old_name

Fixed by undoing renaming link if renaming kobject failed.

Fixes: f349cf34731c ("driver core: Implement ns directory support for device classes.")
Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
Link: https://lore.kernel.org/r/20240722-device_rename_fix-v2-1-77de1a6c6495@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/base/core.c

index b5399262198a68f0209d81004cc062dcbc09f878..6c1a944c00d9b3ea12deed68c0b26aee4c55e7a4 100644 (file)
@@ -4515,9 +4515,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
  */
 int device_rename(struct device *dev, const char *new_name)
 {
+       struct subsys_private *sp = NULL;
        struct kobject *kobj = &dev->kobj;
        char *old_device_name = NULL;
        int error;
+       bool is_link_renamed = false;
 
        dev = get_device(dev);
        if (!dev)
@@ -4532,7 +4534,7 @@ int device_rename(struct device *dev, const char *new_name)
        }
 
        if (dev->class) {
-               struct subsys_private *sp = class_to_subsys(dev->class);
+               sp = class_to_subsys(dev->class);
 
                if (!sp) {
                        error = -EINVAL;
@@ -4541,16 +4543,19 @@ int device_rename(struct device *dev, const char *new_name)
 
                error = sysfs_rename_link_ns(&sp->subsys.kobj, kobj, old_device_name,
                                             new_name, kobject_namespace(kobj));
-               subsys_put(sp);
                if (error)
                        goto out;
+
+               is_link_renamed = true;
        }
 
        error = kobject_rename(kobj, new_name);
-       if (error)
-               goto out;
-
 out:
+       if (error && is_link_renamed)
+               sysfs_rename_link_ns(&sp->subsys.kobj, kobj, new_name,
+                                    old_device_name, kobject_namespace(kobj));
+       subsys_put(sp);
+
        put_device(dev);
 
        kfree(old_device_name);