}
 EXPORT_SYMBOL_GPL(device_move);
 
+static int device_attrs_change_owner(struct device *dev, kuid_t kuid,
+                                    kgid_t kgid)
+{
+       struct kobject *kobj = &dev->kobj;
+       struct class *class = dev->class;
+       const struct device_type *type = dev->type;
+       int error;
+
+       if (class) {
+               /*
+                * Change the device groups of the device class for @dev to
+                * @kuid/@kgid.
+                */
+               error = sysfs_groups_change_owner(kobj, class->dev_groups, kuid,
+                                                 kgid);
+               if (error)
+                       return error;
+       }
+
+       if (type) {
+               /*
+                * Change the device groups of the device type for @dev to
+                * @kuid/@kgid.
+                */
+               error = sysfs_groups_change_owner(kobj, type->groups, kuid,
+                                                 kgid);
+               if (error)
+                       return error;
+       }
+
+       /* Change the device groups of @dev to @kuid/@kgid. */
+       error = sysfs_groups_change_owner(kobj, dev->groups, kuid, kgid);
+       if (error)
+               return error;
+
+       if (device_supports_offline(dev) && !dev->offline_disabled) {
+               /* Change online device attributes of @dev to @kuid/@kgid. */
+               error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
+                                               kuid, kgid);
+               if (error)
+                       return error;
+       }
+
+       return 0;
+}
+
+/**
+ * device_change_owner - change the owner of an existing device.
+ * @dev: device.
+ * @kuid: new owner's kuid
+ * @kgid: new owner's kgid
+ *
+ * This changes the owner of @dev and its corresponding sysfs entries to
+ * @kuid/@kgid. This function closely mirrors how @dev was added via driver
+ * core.
+ *
+ * Returns 0 on success or error code on failure.
+ */
+int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)
+{
+       int error;
+       struct kobject *kobj = &dev->kobj;
+
+       dev = get_device(dev);
+       if (!dev)
+               return -EINVAL;
+
+       /*
+        * Change the kobject and the default attributes and groups of the
+        * ktype associated with it to @kuid/@kgid.
+        */
+       error = sysfs_change_owner(kobj, kuid, kgid);
+       if (error)
+               goto out;
+
+       /*
+        * Change the uevent file for @dev to the new owner. The uevent file
+        * was created in a separate step when @dev got added and we mirror
+        * that step here.
+        */
+       error = sysfs_file_change_owner(kobj, dev_attr_uevent.attr.name, kuid,
+                                       kgid);
+       if (error)
+               goto out;
+
+       /*
+        * Change the device groups, the device groups associated with the
+        * device class, and the groups associated with the device type of @dev
+        * to @kuid/@kgid.
+        */
+       error = device_attrs_change_owner(dev, kuid, kgid);
+       if (error)
+               goto out;
+
+#ifdef CONFIG_BLOCK
+       if (sysfs_deprecated && dev->class == &block_class)
+               goto out;
+#endif
+
+       /*
+        * Change the owner of the symlink located in the class directory of
+        * the device class associated with @dev which points to the actual
+        * directory entry for @dev to @kuid/@kgid. This ensures that the
+        * symlink shows the same permissions as its target.
+        */
+       error = sysfs_link_change_owner(&dev->class->p->subsys.kobj, &dev->kobj,
+                                       dev_name(dev), kuid, kgid);
+       if (error)
+               goto out;
+
+out:
+       put_device(dev);
+       return error;
+}
+EXPORT_SYMBOL_GPL(device_change_owner);
+
 /**
  * device_shutdown - call ->shutdown() on each device to shutdown.
  */