summaryrefslogtreecommitdiff
path: root/drivers/platform
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2021-11-28 20:00:28 +0100
committerHans de Goede <hdegoede@redhat.com>2021-12-06 22:33:35 +0100
commit9918878676a5f9e99b98679f04b9e6c0f5426b0a (patch)
treeaeb2410cc8c39fb9cfa8c7e77257a605fee223ef /drivers/platform
parenta90b38c58667142ecff2521481ed44286d46b140 (diff)
platform/x86: wmi: Fix driver->notify() vs ->probe() race
The driver core sets struct device->driver before calling out to the bus' probe() method, this leaves a window where an ACPI notify may happen on the WMI object before the driver's probe() method has completed running, causing e.g. the driver's notify() callback to get called with drvdata not yet being set leading to a NULL pointer deref. At a check for this to the WMI core, ensuring that the notify() callback is not called before the driver is ready. Fixes: 1686f5444546 ("platform/x86: wmi: Incorporate acpi_install_notify_handler") Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Link: https://lore.kernel.org/r/20211128190031.405620-2-hdegoede@redhat.com
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/wmi.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 46178e03aeca..02aba274c4bc 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -59,6 +59,7 @@ static_assert(__alignof__(struct guid_block) == 1);
enum { /* wmi_block flags */
WMI_READ_TAKES_NO_ARGS,
+ WMI_PROBED,
};
struct wmi_block {
@@ -1008,6 +1009,7 @@ static int wmi_dev_probe(struct device *dev)
}
}
+ set_bit(WMI_PROBED, &wblock->flags);
return 0;
probe_misc_failure:
@@ -1025,6 +1027,8 @@ static void wmi_dev_remove(struct device *dev)
struct wmi_block *wblock = dev_to_wblock(dev);
struct wmi_driver *wdriver = drv_to_wdrv(dev->driver);
+ clear_bit(WMI_PROBED, &wblock->flags);
+
if (wdriver->filter_callback) {
misc_deregister(&wblock->char_dev);
kfree(wblock->char_dev.name);
@@ -1322,7 +1326,7 @@ static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
return;
/* If a driver is bound, then notify the driver. */
- if (wblock->dev.dev.driver) {
+ if (test_bit(WMI_PROBED, &wblock->flags) && wblock->dev.dev.driver) {
struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver);
struct acpi_buffer evdata = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_status status;