Re: kernel oops after ACPI dock initialization fails

From: Chuck Ebbert
Date: Tue May 08 2007 - 17:54:53 EST


Chuck Ebbert wrote:
> In 2.6.21.1 when dock driver initialization fails it does a kfree()
> of dock_station. (Below, this is due to some error installing a
> notify handler.) Later when a bay is discovered it calls
> is_dock_device() which attempts to lock the (nonexistent)
> dock_station. Reason is this test in is_dock_device():
>
> if (!dock_station)
> return 0;
>
> dock_station is 0x6b6b6b6b after being freed. Either it needs
> to be zeroed or some other flag should be used to decide
> whether a dock station is present...
>

Untested patch attached.


---
drivers/acpi/dock.c | 6 ++++++
1 file changed, 6 insertions(+)

--- 2.6.21-d390.orig/drivers/acpi/dock.c
+++ 2.6.21-d390/drivers/acpi/dock.c
@@ -698,6 +698,7 @@ static int dock_add(acpi_handle handle)
if (ret) {
printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
kfree(dock_station);
+ dock_station = NULL;
return ret;
}
ret = device_create_file(&dock_device.dev, &dev_attr_docked);
@@ -705,6 +706,7 @@ static int dock_add(acpi_handle handle)
printk("Error %d adding sysfs file\n", ret);
platform_device_unregister(&dock_device);
kfree(dock_station);
+ dock_station = NULL;
return ret;
}
ret = device_create_file(&dock_device.dev, &dev_attr_undock);
@@ -713,6 +715,7 @@ static int dock_add(acpi_handle handle)
device_remove_file(&dock_device.dev, &dev_attr_docked);
platform_device_unregister(&dock_device);
kfree(dock_station);
+ dock_station = NULL;
return ret;
}

@@ -725,6 +728,7 @@ static int dock_add(acpi_handle handle)
dd = alloc_dock_dependent_device(handle);
if (!dd) {
kfree(dock_station);
+ dock_station = NULL;
ret = -ENOMEM;
goto dock_add_err_unregister;
}
@@ -752,6 +756,7 @@ dock_add_err_unregister:
device_remove_file(&dock_device.dev, &dev_attr_undock);
platform_device_unregister(&dock_device);
kfree(dock_station);
+ dock_station = NULL;
return ret;
}

@@ -785,6 +790,7 @@ static int dock_remove(void)

/* free dock station memory */
kfree(dock_station);
+ dock_station = NULL;
return 0;
}