summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Wolf <W_Armin@gmx.de>2024-10-02 00:28:34 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-10-10 13:01:12 +0300
commitca26e8eed9c1c6651f51f7fa38fe444f8573cd1b (patch)
tree3c551767440f0e008dc81e7371a7efcd33d721d8
parent31ffdcb2b302306a0d8a64ba30896b8ac4b84473 (diff)
downloadlinux-ca26e8eed9c1c6651f51f7fa38fe444f8573cd1b.tar.xz
ACPI: battery: Fix possible crash when unregistering a battery hook
[ Upstream commit 76959aff14a0012ad6b984ec7686d163deccdc16 ] When a battery hook returns an error when adding a new battery, then the battery hook is automatically unregistered. However the battery hook provider cannot know that, so it will later call battery_hook_unregister() on the already unregistered battery hook, resulting in a crash. Fix this by using the list head to mark already unregistered battery hooks as already being unregistered so that they can be ignored by battery_hook_unregister(). Fixes: fa93854f7a7e ("battery: Add the battery hooking API") Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://patch.msgid.link/20241001212835.341788-3-W_Armin@gmx.de Cc: All applicable <stable@vger.kernel.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/acpi/battery.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 04610036e5dc..916cdf44be89 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -715,7 +715,7 @@ static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
if (!hook->remove_battery(battery->bat, hook))
power_supply_changed(battery->bat);
}
- list_del(&hook->list);
+ list_del_init(&hook->list);
pr_info("extension unregistered: %s\n", hook->name);
}
@@ -723,7 +723,14 @@ static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
void battery_hook_unregister(struct acpi_battery_hook *hook)
{
mutex_lock(&hook_mutex);
- battery_hook_unregister_unlocked(hook);
+ /*
+ * Ignore already unregistered battery hooks. This might happen
+ * if a battery hook was previously unloaded due to an error when
+ * adding a new battery.
+ */
+ if (!list_empty(&hook->list))
+ battery_hook_unregister_unlocked(hook);
+
mutex_unlock(&hook_mutex);
}
EXPORT_SYMBOL_GPL(battery_hook_unregister);
@@ -733,7 +740,6 @@ void battery_hook_register(struct acpi_battery_hook *hook)
struct acpi_battery *battery;
mutex_lock(&hook_mutex);
- INIT_LIST_HEAD(&hook->list);
list_add(&hook->list, &battery_hook_list);
/*
* Now that the driver is registered, we need