Patch "driver core: fix race between creating/querying glue dir and its cleanup" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
driver core: fix race between creating/querying glue dir and its cleanup
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
driver-core-fix-race-between-creating-querying-glue-dir-and-its-cleanup.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
cebf8fd16900fdfd58c0028617944f808f97fe50Mon Sep 17 00:00:00 2001
From: Ming Lei <[email protected]>
Date: Sun, 10 Jul 2016 19:27:36 +0800
Subject: driver core: fix race between creating/querying glue dir and its cleanup
From: Ming Lei <[email protected]>
commit cebf8fd16900fdfd58c0028617944f808f97fe50 upstream.
The global mutex of 'gdp_mutex' is used to serialize creating/querying glue dir and its cleanup. Turns out it isn't a perfect way because part(kobj_kset_leave()) of the actual cleanup action() is done inside the release handler of the glue dir kobject. That means gdp_mutex has to be held before releasing the last reference count of the glue dir kobject.
This patch moves glue dir's cleanup after kobject_del() in device_del() for avoiding the race.
--- drivers/base/core.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-)
drivers/base/core.c +29 -10
@@ -836,11 +836,29 @@ static struct kobject *get_device_parentreturn NULL ; } +static inline bool live_in_glue_dir (struct kobject *kobj, +struct device *dev) +{ +if (!kobj || !dev->class || + kobj->kset != &dev->class->p->glue_dirs) +return false; +return true; +} + +static inline struct kobject *get_glue_dir (struct device *dev) +{ +return dev->kobj.parent; +} + +/* +* make sure cleaning up dir as the last step, we need to make +* sure .release handler of kobject is run with holding the +* global lock +*/ static void cleanup_glue_dir (struct device *dev,struct kobject *glue_dir) {/* see if we live in a "glue" directory */ -if (!glue_dir || !dev->class || - glue_dir->kset != &dev->class->p->glue_dirs) +if (!live_in_glue_dir (glue_dir, dev))return ;mutex_lock (&gdp_mutex);
@@ -848,11 +866,6 @@ static void cleanup_glue_dir(struct devimutex_unlock (&gdp_mutex); } -static void cleanup_device_parent (struct device *dev) -{ -cleanup_glue_dir (dev, dev->kobj.parent); -} -static int device_add_class_symlinks (struct device *dev) {struct device_node *of_node =dev_of_node (dev);
@@ -1028,6 +1041,7 @@ int device_add(struct device *dev)struct kobject *kobj;struct class_interface *class_intf;int error = -EINVAL ; +struct kobject *glue_dir =NULL ; dev =get_device (dev);if (!dev)
@@ -1072,8 +1086,10 @@ int device_add(struct device *dev)/* first, register with generic layer. */ /* we require the name to be set before, and pass NULL */ error =kobject_add (&dev->kobj, dev->kobj.parent,NULL ); -if (error) +if (error) { + glue_dir =get_glue_dir (dev); goto Error; + }/* notify platform of device entry */ if (platform_notify)
@@ -1154,9 +1170,10 @@ done:device_remove_file (dev, &dev_attr_uevent); attrError:kobject_uevent (&dev->kobj,KOBJ_REMOVE ); + glue_dir =get_glue_dir (dev);kobject_del (&dev->kobj); Error: -cleanup_device_parent (dev); +cleanup_glue_dir (dev, glue_dir);put_device (parent); name_error:kfree (dev->p);
@@ -1232,6 +1249,7 @@ EXPORT_SYMBOL_GPL(put_device);void device_del (struct device *dev) {struct device *parent = dev->parent; +struct kobject *glue_dir =NULL ;struct class_interface *class_intf;/* Notify clients of device removal. This call must come
@@ -1276,8 +1294,9 @@ void device_del(struct device *dev)blocking_notifier_call_chain (&dev->bus->p->bus_notifier,BUS_NOTIFY_REMOVED_DEVICE , dev);kobject_uevent (&dev->kobj,KOBJ_REMOVE ); -cleanup_device_parent (dev); + glue_dir =get_glue_dir (dev);kobject_del (&dev->kobj); +cleanup_glue_dir (dev, glue_dir);put_device (parent); }EXPORT_SYMBOL_GPL (device_del);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/driver-core-fix-race-between-creating-querying-glue-dir-and-its-cleanup.patch