diff options
author | Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> | 2011-07-12 12:03:28 +0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-07-17 02:54:59 +0400 |
commit | e80bba4b5108c6479379740201b0a5d9da5ffbac (patch) | |
tree | 34634eebb8dc8f17e8654ffff0d5b6b2fb3a370b | |
parent | 9c921c22a7f33397a6774d7fa076db9b6a0fd669 (diff) | |
download | linux-e80bba4b5108c6479379740201b0a5d9da5ffbac.tar.xz |
ACPI / Battery: avoid acpi_battery_add() use-after-free
When acpi_battery_add_fs() fails the error handling code does not clean
up completely. Moreover, it does not return resulting in a
use-after-free.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/battery.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 40bf01d42cc3..c771768f57c8 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -986,21 +986,27 @@ static int acpi_battery_add(struct acpi_device *device) #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); #endif - if (!result) { - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", - ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), - device->status.battery_present ? "present" : "absent"); - } else { + if (result) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif - kfree(battery); + goto fail; } + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present ? "present" : "absent"); + battery->pm_nb.notifier_call = battery_notify; register_pm_notifier(&battery->pm_nb); return result; + +fail: + sysfs_remove_battery(battery); + mutex_destroy(&battery->lock); + kfree(battery); + return result; } static int acpi_battery_remove(struct acpi_device *device, int type) |