From: Sergey Klyaus Date: Wed, 8 Oct 2014 07:31:54 +0000 (+0400) Subject: driver core: fix race with userland in device_add() X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=0cd75047de7f54d6fb4aba0ec5818f8194815a5a;p=linux-beck.git driver core: fix race with userland in device_add() bus_add_device() should be called before devtmpfs_create_node(), so when userland application opens device from devtmpfs, it wouldn't get ENODEV from kernel, because device_add() wasn't completed. Signed-off-by: Sergey Klyaus Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/base/core.c b/drivers/base/core.c index 14d162952c3b..00ec7ce6f3e3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1019,18 +1019,6 @@ int device_add(struct device *dev) if (error) goto attrError; - if (MAJOR(dev->devt)) { - error = device_create_file(dev, &dev_attr_dev); - if (error) - goto ueventattrError; - - error = device_create_sys_dev_entry(dev); - if (error) - goto devtattrError; - - devtmpfs_create_node(dev); - } - error = device_add_class_symlinks(dev); if (error) goto SymlinkError; @@ -1045,6 +1033,18 @@ int device_add(struct device *dev) goto DPMError; device_pm_add(dev); + if (MAJOR(dev->devt)) { + error = device_create_file(dev, &dev_attr_dev); + if (error) + goto DevAttrError; + + error = device_create_sys_dev_entry(dev); + if (error) + goto SysEntryError; + + devtmpfs_create_node(dev); + } + /* Notify clients of device addition. This call must come * after dpm_sysfs_add() and before kobject_uevent(). */ @@ -1074,6 +1074,12 @@ int device_add(struct device *dev) done: put_device(dev); return error; + SysEntryError: + if (MAJOR(dev->devt)) + device_remove_file(dev, &dev_attr_dev); + DevAttrError: + device_pm_remove(dev); + dpm_sysfs_remove(dev); DPMError: bus_remove_device(dev); BusError: @@ -1081,14 +1087,6 @@ done: AttrsError: device_remove_class_symlinks(dev); SymlinkError: - if (MAJOR(dev->devt)) - devtmpfs_delete_node(dev); - if (MAJOR(dev->devt)) - device_remove_sys_dev_entry(dev); - devtattrError: - if (MAJOR(dev->devt)) - device_remove_file(dev, &dev_attr_dev); - ueventattrError: device_remove_file(dev, &dev_attr_uevent); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE);