aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorSergey Klyaus <Sergey.Klyaus@tune-it.ru>2014-10-08 03:31:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-07 14:14:57 -0500
commit0cd75047de7f54d6fb4aba0ec5818f8194815a5a (patch)
tree32fd93ff2934eef026907e747ee6fe6456785687 /drivers/base
parent4ef67a8c95f32ed0c8c6ed5fe01d1dd16358350e (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.c38
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)
1074done: 1074done:
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);