Subject: [PATCH] kobject: fix the race between kobject_del and get_device_parent

From: Weng Meiling
Date: Wed Oct 15 2014 - 02:43:29 EST


When the last child kobject was deleted, it's parent kobject will be deleted,
when removing the parent kobject if the parent kobject's sd has been set NULL
and still not been removed from it's kset's list, at the same time another one
trigger an device adding event, the function get_parent_device() will get the
parent object from the kset's list for kobject_add(), but this time parent
kobject's sd has been NULL. This race will make the sysfs_create_dir() return
ENOENT, the new kobject will be failed to added into sysfs and trigger BUG()
when creating attribute group under the new device's directory. So move the
kobject removal from kset's list before kobj->sd=NULL.

The race situation:

path0(remove parent kobj, e.g:/sys/devices/virtual/block/) path1(register a new device)

kobject_del(){ get_device_parent(){
... ...
sysfs_remove_dir(kobj); //kobj->sd=NULL spin_lock(&dev->class->p->glue_dirs.list_lock);
... <=== list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry)
kobj_kset_leave(kobj); //remove kobj from kset list ...
} }


We had triggered the bug, the detail message link:
https://lkml.org/lkml/2014/10/13/40

Signed-off-by: Weng Meiling <wengmeiling.weng@xxxxxxxxxx>
---
lib/kobject.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/kobject.c b/lib/kobject.c
index 58751bb..af2b7bb 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -560,12 +560,13 @@ void kobject_del(struct kobject *kobj)
if (!kobj)
return;

+ kobj_kset_leave(kobj);
+
sd = kobj->sd;
sysfs_remove_dir(kobj);
sysfs_put(sd);

kobj->state_in_sysfs = 0;
- kobj_kset_leave(kobj);
kobject_put(kobj->parent);
kobj->parent = NULL;
}
--
1.8.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/