Skip to content

Commit 8a700b1

Browse files
author
Danilo Krummrich
committed
platform/wmi: use generic driver_override infrastructure
When a driver is probed through __driver_attach(), the bus' match() callback is called without the device lock held, thus accessing the driver_override field without a lock, which can cause a UAF. Fix this by using the driver-core driver_override infrastructure taking care of proper locking internally. Note that calling match() from __driver_attach() without the device lock held is intentional. [1] Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1] Reported-by: Gui-Dong Han <hanguidong02@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 Fixes: 12046f8 ("platform/x86: wmi: Add driver_override support") Reviewed-by: Armin Wolf <W_Armin@gmx.de> Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Link: https://patch.msgid.link/20260324005919.2408620-7-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent 10a4206 commit 8a700b1

2 files changed

Lines changed: 5 additions & 35 deletions

File tree

drivers/platform/wmi/core.c

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -842,39 +842,11 @@ static ssize_t expensive_show(struct device *dev,
842842
}
843843
static DEVICE_ATTR_RO(expensive);
844844

845-
static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr,
846-
char *buf)
847-
{
848-
struct wmi_device *wdev = to_wmi_device(dev);
849-
ssize_t ret;
850-
851-
device_lock(dev);
852-
ret = sysfs_emit(buf, "%s\n", wdev->driver_override);
853-
device_unlock(dev);
854-
855-
return ret;
856-
}
857-
858-
static ssize_t driver_override_store(struct device *dev, struct device_attribute *attr,
859-
const char *buf, size_t count)
860-
{
861-
struct wmi_device *wdev = to_wmi_device(dev);
862-
int ret;
863-
864-
ret = driver_set_override(dev, &wdev->driver_override, buf, count);
865-
if (ret < 0)
866-
return ret;
867-
868-
return count;
869-
}
870-
static DEVICE_ATTR_RW(driver_override);
871-
872845
static struct attribute *wmi_attrs[] = {
873846
&dev_attr_modalias.attr,
874847
&dev_attr_guid.attr,
875848
&dev_attr_instance_count.attr,
876849
&dev_attr_expensive.attr,
877-
&dev_attr_driver_override.attr,
878850
NULL
879851
};
880852
ATTRIBUTE_GROUPS(wmi);
@@ -943,7 +915,6 @@ static void wmi_dev_release(struct device *dev)
943915
{
944916
struct wmi_block *wblock = dev_to_wblock(dev);
945917

946-
kfree(wblock->dev.driver_override);
947918
kfree(wblock);
948919
}
949920

@@ -952,10 +923,12 @@ static int wmi_dev_match(struct device *dev, const struct device_driver *driver)
952923
const struct wmi_driver *wmi_driver = to_wmi_driver(driver);
953924
struct wmi_block *wblock = dev_to_wblock(dev);
954925
const struct wmi_device_id *id = wmi_driver->id_table;
926+
int ret;
955927

956928
/* When driver_override is set, only bind to the matching driver */
957-
if (wblock->dev.driver_override)
958-
return !strcmp(wblock->dev.driver_override, driver->name);
929+
ret = device_match_driver_override(dev, driver);
930+
if (ret >= 0)
931+
return ret;
959932

960933
if (id == NULL)
961934
return 0;
@@ -1076,6 +1049,7 @@ static struct class wmi_bus_class = {
10761049
static const struct bus_type wmi_bus_type = {
10771050
.name = "wmi",
10781051
.dev_groups = wmi_groups,
1052+
.driver_override = true,
10791053
.match = wmi_dev_match,
10801054
.uevent = wmi_dev_uevent,
10811055
.probe = wmi_dev_probe,

include/linux/wmi.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,12 @@
1818
* struct wmi_device - WMI device structure
1919
* @dev: Device associated with this WMI device
2020
* @setable: True for devices implementing the Set Control Method
21-
* @driver_override: Driver name to force a match; do not set directly,
22-
* because core frees it; use driver_set_override() to
23-
* set or clear it.
2421
*
2522
* This represents WMI devices discovered by the WMI driver core.
2623
*/
2724
struct wmi_device {
2825
struct device dev;
2926
bool setable;
30-
const char *driver_override;
3127
};
3228

3329
/**

0 commit comments

Comments
 (0)