diff options
author | Sergey Klyaus <Sergey.Klyaus@tune-it.ru> | 2014-10-08 03:31:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-07 14:14:57 -0500 |
commit | 0cd75047de7f54d6fb4aba0ec5818f8194815a5a (patch) | |
tree | 32fd93ff2934eef026907e747ee6fe6456785687 /drivers/base | |
parent | 4ef67a8c95f32ed0c8c6ed5fe01d1dd16358350e (diff) |
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 <Sergey.Klyaus@Tune-IT.Ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 38 |
1 files changed, 18 insertions, 20 deletions
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) | |||
1019 | if (error) | 1019 | if (error) |
1020 | goto attrError; | 1020 | goto attrError; |
1021 | 1021 | ||
1022 | if (MAJOR(dev->devt)) { | ||
1023 | error = device_create_file(dev, &dev_attr_dev); | ||
1024 | if (error) | ||
1025 | goto ueventattrError; | ||
1026 | |||
1027 | error = device_create_sys_dev_entry(dev); | ||
1028 | if (error) | ||
1029 | goto devtattrError; | ||
1030 | |||
1031 | devtmpfs_create_node(dev); | ||
1032 | } | ||
1033 | |||
1034 | error = device_add_class_symlinks(dev); | 1022 | error = device_add_class_symlinks(dev); |
1035 | if (error) | 1023 | if (error) |
1036 | goto SymlinkError; | 1024 | goto SymlinkError; |
@@ -1045,6 +1033,18 @@ int device_add(struct device *dev) | |||
1045 | goto DPMError; | 1033 | goto DPMError; |
1046 | device_pm_add(dev); | 1034 | device_pm_add(dev); |
1047 | 1035 | ||
1036 | if (MAJOR(dev->devt)) { | ||
1037 | error = device_create_file(dev, &dev_attr_dev); | ||
1038 | if (error) | ||
1039 | goto DevAttrError; | ||
1040 | |||
1041 | error = device_create_sys_dev_entry(dev); | ||
1042 | if (error) | ||
1043 | goto SysEntryError; | ||
1044 | |||
1045 | devtmpfs_create_node(dev); | ||
1046 | } | ||
1047 | |||
1048 | /* Notify clients of device addition. This call must come | 1048 | /* Notify clients of device addition. This call must come |
1049 | * after dpm_sysfs_add() and before kobject_uevent(). | 1049 | * after dpm_sysfs_add() and before kobject_uevent(). |
1050 | */ | 1050 | */ |
@@ -1074,6 +1074,12 @@ int device_add(struct device *dev) | |||
1074 | done: | 1074 | done: |
1075 | put_device(dev); | 1075 | put_device(dev); |
1076 | return error; | 1076 | return error; |
1077 | SysEntryError: | ||
1078 | if (MAJOR(dev->devt)) | ||
1079 | device_remove_file(dev, &dev_attr_dev); | ||
1080 | DevAttrError: | ||
1081 | device_pm_remove(dev); | ||
1082 | dpm_sysfs_remove(dev); | ||
1077 | DPMError: | 1083 | DPMError: |
1078 | bus_remove_device(dev); | 1084 | bus_remove_device(dev); |
1079 | BusError: | 1085 | BusError: |
@@ -1081,14 +1087,6 @@ done: | |||
1081 | AttrsError: | 1087 | AttrsError: |
1082 | device_remove_class_symlinks(dev); | 1088 | device_remove_class_symlinks(dev); |
1083 | SymlinkError: | 1089 | SymlinkError: |
1084 | if (MAJOR(dev->devt)) | ||
1085 | devtmpfs_delete_node(dev); | ||
1086 | if (MAJOR(dev->devt)) | ||
1087 | device_remove_sys_dev_entry(dev); | ||
1088 | devtattrError: | ||
1089 | if (MAJOR(dev->devt)) | ||
1090 | device_remove_file(dev, &dev_attr_dev); | ||
1091 | ueventattrError: | ||
1092 | device_remove_file(dev, &dev_attr_uevent); | 1090 | device_remove_file(dev, &dev_attr_uevent); |
1093 | attrError: | 1091 | attrError: |
1094 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); | 1092 | kobject_uevent(&dev->kobj, KOBJ_REMOVE); |