diff options
author | Krzysztof Kozlowski <k.kozlowski@samsung.com> | 2015-05-19 03:13:02 -0400 |
---|---|---|
committer | Sebastian Reichel <sre@kernel.org> | 2015-05-21 09:41:09 -0400 |
commit | 7f1a57fdd6cb6e7be2ed31878a34655df38e1861 (patch) | |
tree | 20413d06df4c75d7fbdb2aafab6b801808418555 /drivers/power | |
parent | 8e59c7f23410d5ca6b350a178b861a3d68c49edf (diff) |
power_supply: Fix possible NULL pointer dereference on early uevent
Don't call the power_supply_changed() from power_supply_register() when
parent is still probing because it may lead to accessing parent too
early.
In bq27x00_battery this caused NULL pointer exception because uevent of
power_supply_changed called back the the get_property() method provided
by the driver. The get_property() method accessed pointer which should
be returned by power_supply_register().
Starting from bq27x00_battery_probe():
di->bat = power_supply_register()
power_supply_changed()
kobject_uevent()
power_supply_uevent()
power_supply_show_property()
power_supply_get_property()
bq27x00_battery_get_property()
dereference of di->bat which is NULL here
The dereference of di->bat (value returned by power_supply_register())
is the currently visible problem. However calling back the methods
provided by driver before ending the probe may lead to accessing other
driver-related data which is not yet initialized.
The call to power_supply_changed() is postponed till probing ends -
mutex of parent device is released.
Reported-by: H. Nikolaus Schaller <hns@goldelico.com>
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
Fixes: 297d716f6260 ("power_supply: Change ownership from driver to core")
Tested-By: Dr. H. Nikolaus Schaller <hns@goldelico.com>
Signed-off-by: Sebastian Reichel <sre@kernel.org>
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/power_supply_core.c | 50 |
1 files changed, 45 insertions, 5 deletions
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c index 15da277e0e8d..4bc0c7f459a5 100644 --- a/drivers/power/power_supply_core.c +++ b/drivers/power/power_supply_core.c | |||
@@ -30,6 +30,8 @@ EXPORT_SYMBOL_GPL(power_supply_notifier); | |||
30 | 30 | ||
31 | static struct device_type power_supply_dev_type; | 31 | static struct device_type power_supply_dev_type; |
32 | 32 | ||
33 | #define POWER_SUPPLY_DEFERRED_REGISTER_TIME msecs_to_jiffies(10) | ||
34 | |||
33 | static bool __power_supply_is_supplied_by(struct power_supply *supplier, | 35 | static bool __power_supply_is_supplied_by(struct power_supply *supplier, |
34 | struct power_supply *supply) | 36 | struct power_supply *supply) |
35 | { | 37 | { |
@@ -121,6 +123,30 @@ void power_supply_changed(struct power_supply *psy) | |||
121 | } | 123 | } |
122 | EXPORT_SYMBOL_GPL(power_supply_changed); | 124 | EXPORT_SYMBOL_GPL(power_supply_changed); |
123 | 125 | ||
126 | /* | ||
127 | * Notify that power supply was registered after parent finished the probing. | ||
128 | * | ||
129 | * Often power supply is registered from driver's probe function. However | ||
130 | * calling power_supply_changed() directly from power_supply_register() | ||
131 | * would lead to execution of get_property() function provided by the driver | ||
132 | * too early - before the probe ends. | ||
133 | * | ||
134 | * Avoid that by waiting on parent's mutex. | ||
135 | */ | ||
136 | static void power_supply_deferred_register_work(struct work_struct *work) | ||
137 | { | ||
138 | struct power_supply *psy = container_of(work, struct power_supply, | ||
139 | deferred_register_work.work); | ||
140 | |||
141 | if (psy->dev.parent) | ||
142 | mutex_lock(&psy->dev.parent->mutex); | ||
143 | |||
144 | power_supply_changed(psy); | ||
145 | |||
146 | if (psy->dev.parent) | ||
147 | mutex_unlock(&psy->dev.parent->mutex); | ||
148 | } | ||
149 | |||
124 | #ifdef CONFIG_OF | 150 | #ifdef CONFIG_OF |
125 | #include <linux/of.h> | 151 | #include <linux/of.h> |
126 | 152 | ||
@@ -645,6 +671,10 @@ __power_supply_register(struct device *parent, | |||
645 | struct power_supply *psy; | 671 | struct power_supply *psy; |
646 | int rc; | 672 | int rc; |
647 | 673 | ||
674 | if (!parent) | ||
675 | pr_warn("%s: Expected proper parent device for '%s'\n", | ||
676 | __func__, desc->name); | ||
677 | |||
648 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); | 678 | psy = kzalloc(sizeof(*psy), GFP_KERNEL); |
649 | if (!psy) | 679 | if (!psy) |
650 | return ERR_PTR(-ENOMEM); | 680 | return ERR_PTR(-ENOMEM); |
@@ -671,6 +701,8 @@ __power_supply_register(struct device *parent, | |||
671 | goto dev_set_name_failed; | 701 | goto dev_set_name_failed; |
672 | 702 | ||
673 | INIT_WORK(&psy->changed_work, power_supply_changed_work); | 703 | INIT_WORK(&psy->changed_work, power_supply_changed_work); |
704 | INIT_DELAYED_WORK(&psy->deferred_register_work, | ||
705 | power_supply_deferred_register_work); | ||
674 | 706 | ||
675 | rc = power_supply_check_supplies(psy); | 707 | rc = power_supply_check_supplies(psy); |
676 | if (rc) { | 708 | if (rc) { |
@@ -709,7 +741,10 @@ __power_supply_register(struct device *parent, | |||
709 | * after calling power_supply_register()). | 741 | * after calling power_supply_register()). |
710 | */ | 742 | */ |
711 | atomic_inc(&psy->use_cnt); | 743 | atomic_inc(&psy->use_cnt); |
712 | power_supply_changed(psy); | 744 | |
745 | queue_delayed_work(system_power_efficient_wq, | ||
746 | &psy->deferred_register_work, | ||
747 | POWER_SUPPLY_DEFERRED_REGISTER_TIME); | ||
713 | 748 | ||
714 | return psy; | 749 | return psy; |
715 | 750 | ||
@@ -729,7 +764,8 @@ dev_set_name_failed: | |||
729 | 764 | ||
730 | /** | 765 | /** |
731 | * power_supply_register() - Register new power supply | 766 | * power_supply_register() - Register new power supply |
732 | * @parent: Device to be a parent of power supply's device | 767 | * @parent: Device to be a parent of power supply's device, usually |
768 | * the device which probe function calls this | ||
733 | * @desc: Description of power supply, must be valid through whole | 769 | * @desc: Description of power supply, must be valid through whole |
734 | * lifetime of this power supply | 770 | * lifetime of this power supply |
735 | * @cfg: Run-time specific configuration accessed during registering, | 771 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -750,7 +786,8 @@ EXPORT_SYMBOL_GPL(power_supply_register); | |||
750 | 786 | ||
751 | /** | 787 | /** |
752 | * power_supply_register() - Register new non-waking-source power supply | 788 | * power_supply_register() - Register new non-waking-source power supply |
753 | * @parent: Device to be a parent of power supply's device | 789 | * @parent: Device to be a parent of power supply's device, usually |
790 | * the device which probe function calls this | ||
754 | * @desc: Description of power supply, must be valid through whole | 791 | * @desc: Description of power supply, must be valid through whole |
755 | * lifetime of this power supply | 792 | * lifetime of this power supply |
756 | * @cfg: Run-time specific configuration accessed during registering, | 793 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -779,7 +816,8 @@ static void devm_power_supply_release(struct device *dev, void *res) | |||
779 | 816 | ||
780 | /** | 817 | /** |
781 | * power_supply_register() - Register managed power supply | 818 | * power_supply_register() - Register managed power supply |
782 | * @parent: Device to be a parent of power supply's device | 819 | * @parent: Device to be a parent of power supply's device, usually |
820 | * the device which probe function calls this | ||
783 | * @desc: Description of power supply, must be valid through whole | 821 | * @desc: Description of power supply, must be valid through whole |
784 | * lifetime of this power supply | 822 | * lifetime of this power supply |
785 | * @cfg: Run-time specific configuration accessed during registering, | 823 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -814,7 +852,8 @@ EXPORT_SYMBOL_GPL(devm_power_supply_register); | |||
814 | 852 | ||
815 | /** | 853 | /** |
816 | * power_supply_register() - Register managed non-waking-source power supply | 854 | * power_supply_register() - Register managed non-waking-source power supply |
817 | * @parent: Device to be a parent of power supply's device | 855 | * @parent: Device to be a parent of power supply's device, usually |
856 | * the device which probe function calls this | ||
818 | * @desc: Description of power supply, must be valid through whole | 857 | * @desc: Description of power supply, must be valid through whole |
819 | * lifetime of this power supply | 858 | * lifetime of this power supply |
820 | * @cfg: Run-time specific configuration accessed during registering, | 859 | * @cfg: Run-time specific configuration accessed during registering, |
@@ -858,6 +897,7 @@ void power_supply_unregister(struct power_supply *psy) | |||
858 | { | 897 | { |
859 | WARN_ON(atomic_dec_return(&psy->use_cnt)); | 898 | WARN_ON(atomic_dec_return(&psy->use_cnt)); |
860 | cancel_work_sync(&psy->changed_work); | 899 | cancel_work_sync(&psy->changed_work); |
900 | cancel_delayed_work_sync(&psy->deferred_register_work); | ||
861 | sysfs_remove_link(&psy->dev.kobj, "powers"); | 901 | sysfs_remove_link(&psy->dev.kobj, "powers"); |
862 | power_supply_remove_triggers(psy); | 902 | power_supply_remove_triggers(psy); |
863 | psy_unregister_cooler(psy); | 903 | psy_unregister_cooler(psy); |