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

Commit d472c78c authored by bumwoo lee's avatar bumwoo lee Committed by Greg Kroah-Hartman
Browse files

extcon: Modify extcon device to be created after driver data is set



[ Upstream commit 5dcc2afe716d69f5112ce035cb14f007461ff189 ]

Currently, someone can invoke the sysfs such as state_show()
intermittently before dev_set_drvdata() is done.
And it can be a cause of kernel Oops because of edev is Null at that time.
So modified the driver registration to after setting drviver data.

- Oops's backtrace.

Backtrace:
[<c067865c>] (state_show) from [<c05222e8>] (dev_attr_show)
[<c05222c0>] (dev_attr_show) from [<c02c66e0>] (sysfs_kf_seq_show)
[<c02c6648>] (sysfs_kf_seq_show) from [<c02c496c>] (kernfs_seq_show)
[<c02c4938>] (kernfs_seq_show) from [<c025e2a0>] (seq_read)
[<c025e11c>] (seq_read) from [<c02c50a0>] (kernfs_fop_read)
[<c02c5064>] (kernfs_fop_read) from [<c0231cac>] (__vfs_read)
[<c0231c5c>] (__vfs_read) from [<c0231ee0>] (vfs_read)
[<c0231e34>] (vfs_read) from [<c0232464>] (ksys_read)
[<c02323f0>] (ksys_read) from [<c02324fc>] (sys_read)
[<c02324e4>] (sys_read) from [<c00091d0>] (__sys_trace_return)

Signed-off-by: default avatarbumwoo lee <bw365.lee@samsung.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent fa0b2dd6
Loading
Loading
Loading
Loading
+17 −12
Original line number Diff line number Diff line
@@ -1230,19 +1230,14 @@ int extcon_dev_register(struct extcon_dev *edev)
		edev->dev.type = &edev->extcon_dev_type;
	}

	ret = device_register(&edev->dev);
	if (ret) {
		put_device(&edev->dev);
		goto err_dev;
	}

	spin_lock_init(&edev->lock);
	edev->nh = devm_kcalloc(&edev->dev, edev->max_supported,
				sizeof(*edev->nh), GFP_KERNEL);
	if (edev->max_supported) {
		edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh),
				GFP_KERNEL);
		if (!edev->nh) {
			ret = -ENOMEM;
		device_unregister(&edev->dev);
		goto err_dev;
			goto err_alloc_nh;
		}
	}

	for (index = 0; index < edev->max_supported; index++)
@@ -1253,6 +1248,12 @@ int extcon_dev_register(struct extcon_dev *edev)
	dev_set_drvdata(&edev->dev, edev);
	edev->state = 0;

	ret = device_register(&edev->dev);
	if (ret) {
		put_device(&edev->dev);
		goto err_dev;
	}

	mutex_lock(&extcon_dev_list_lock);
	list_add(&edev->entry, &extcon_dev_list);
	mutex_unlock(&extcon_dev_list_lock);
@@ -1260,6 +1261,9 @@ int extcon_dev_register(struct extcon_dev *edev)
	return 0;

err_dev:
	if (edev->max_supported)
		kfree(edev->nh);
err_alloc_nh:
	if (edev->max_supported)
		kfree(edev->extcon_dev_type.groups);
err_alloc_groups:
@@ -1320,6 +1324,7 @@ void extcon_dev_unregister(struct extcon_dev *edev)
	if (edev->max_supported) {
		kfree(edev->extcon_dev_type.groups);
		kfree(edev->cables);
		kfree(edev->nh);
	}

	put_device(&edev->dev);