Skip to content

Commit

Permalink
driver core: fix race with userland in device_add()
Browse files Browse the repository at this point in the history
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 <Sergey.Klyaus@Tune-IT.Ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Sergey Klyaus authored and Greg Kroah-Hartman committed Nov 7, 2014
1 parent 4ef67a8 commit 0cd7504
Showing 1 changed file with 18 additions and 20 deletions.
38 changes: 18 additions & 20 deletions drivers/base/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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().
*/
Expand Down Expand Up @@ -1074,21 +1074,19 @@ 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:
device_remove_attrs(dev);
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);
Expand Down

0 comments on commit 0cd7504

Please sign in to comment.