Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0cd75047 authored by Sergey Klyaus's avatar Sergey Klyaus Committed by Greg Kroah-Hartman
Browse files

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: default avatarSergey Klyaus <Sergey.Klyaus@Tune-IT.Ru>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4ef67a8c
Loading
Loading
Loading
Loading
+18 −20
Original line number Original line Diff line number Diff line
@@ -1019,18 +1019,6 @@ int device_add(struct device *dev)
	if (error)
	if (error)
		goto attrError;
		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);
	error = device_add_class_symlinks(dev);
	if (error)
	if (error)
		goto SymlinkError;
		goto SymlinkError;
@@ -1045,6 +1033,18 @@ int device_add(struct device *dev)
		goto DPMError;
		goto DPMError;
	device_pm_add(dev);
	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
	/* Notify clients of device addition.  This call must come
	 * after dpm_sysfs_add() and before kobject_uevent().
	 * after dpm_sysfs_add() and before kobject_uevent().
	 */
	 */
@@ -1074,6 +1074,12 @@ int device_add(struct device *dev)
done:
done:
	put_device(dev);
	put_device(dev);
	return error;
	return error;
 SysEntryError:
	if (MAJOR(dev->devt))
		device_remove_file(dev, &dev_attr_dev);
 DevAttrError:
	device_pm_remove(dev);
	dpm_sysfs_remove(dev);
 DPMError:
 DPMError:
	bus_remove_device(dev);
	bus_remove_device(dev);
 BusError:
 BusError:
@@ -1081,14 +1087,6 @@ int device_add(struct device *dev)
 AttrsError:
 AttrsError:
	device_remove_class_symlinks(dev);
	device_remove_class_symlinks(dev);
 SymlinkError:
 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);
	device_remove_file(dev, &dev_attr_uevent);
 attrError:
 attrError:
	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
	kobject_uevent(&dev->kobj, KOBJ_REMOVE);