Skip to content

Commit 6c8dfb0

Browse files
author
Danilo Krummrich
committed
bus: fsl-mc: 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] Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com> Acked-by: Ioana Ciornei <ioana.ciornei@nxp.com> Acked-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org> 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: 1f86a00 ("bus/fsl-mc: add support for 'driver_override' in the mc-bus") Link: https://patch.msgid.link/20260324005919.2408620-3-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent 81d6f7c commit 6c8dfb0

3 files changed

Lines changed: 8 additions & 43 deletions

File tree

drivers/bus/fsl-mc/fsl-mc-bus.c

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,16 @@ static int fsl_mc_bus_match(struct device *dev, const struct device_driver *drv)
8686
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
8787
const struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
8888
bool found = false;
89+
int ret;
8990

9091
/* When driver_override is set, only bind to the matching driver */
91-
if (mc_dev->driver_override) {
92-
found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
92+
ret = device_match_driver_override(dev, drv);
93+
if (ret > 0) {
94+
found = true;
9395
goto out;
9496
}
97+
if (ret == 0)
98+
goto out;
9599

96100
if (!mc_drv->match_id_table)
97101
goto out;
@@ -210,39 +214,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
210214
}
211215
static DEVICE_ATTR_RO(modalias);
212216

213-
static ssize_t driver_override_store(struct device *dev,
214-
struct device_attribute *attr,
215-
const char *buf, size_t count)
216-
{
217-
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
218-
int ret;
219-
220-
if (WARN_ON(dev->bus != &fsl_mc_bus_type))
221-
return -EINVAL;
222-
223-
ret = driver_set_override(dev, &mc_dev->driver_override, buf, count);
224-
if (ret)
225-
return ret;
226-
227-
return count;
228-
}
229-
230-
static ssize_t driver_override_show(struct device *dev,
231-
struct device_attribute *attr, char *buf)
232-
{
233-
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
234-
ssize_t len;
235-
236-
device_lock(dev);
237-
len = sysfs_emit(buf, "%s\n", mc_dev->driver_override);
238-
device_unlock(dev);
239-
return len;
240-
}
241-
static DEVICE_ATTR_RW(driver_override);
242-
243217
static struct attribute *fsl_mc_dev_attrs[] = {
244218
&dev_attr_modalias.attr,
245-
&dev_attr_driver_override.attr,
246219
NULL,
247220
};
248221

@@ -345,6 +318,7 @@ ATTRIBUTE_GROUPS(fsl_mc_bus);
345318

346319
const struct bus_type fsl_mc_bus_type = {
347320
.name = "fsl-mc",
321+
.driver_override = true,
348322
.match = fsl_mc_bus_match,
349323
.uevent = fsl_mc_bus_uevent,
350324
.probe = fsl_mc_probe,
@@ -910,9 +884,6 @@ static struct notifier_block fsl_mc_nb;
910884
*/
911885
void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
912886
{
913-
kfree(mc_dev->driver_override);
914-
mc_dev->driver_override = NULL;
915-
916887
/*
917888
* The device-specific remove callback will get invoked by device_del()
918889
*/

drivers/vfio/fsl-mc/vfio_fsl_mc.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,7 @@ static int vfio_fsl_mc_bus_notifier(struct notifier_block *nb,
424424

425425
if (action == BUS_NOTIFY_ADD_DEVICE &&
426426
vdev->mc_dev == mc_cont) {
427-
mc_dev->driver_override = kasprintf(GFP_KERNEL, "%s",
428-
vfio_fsl_mc_ops.name);
429-
if (!mc_dev->driver_override)
427+
if (device_set_driver_override(dev, vfio_fsl_mc_ops.name))
430428
dev_warn(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s failed\n",
431429
dev_name(&mc_cont->dev));
432430
else

include/linux/fsl/mc.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,6 @@ struct fsl_mc_obj_desc {
178178
* @regions: pointer to array of MMIO region entries
179179
* @irqs: pointer to array of pointers to interrupts allocated to this device
180180
* @resource: generic resource associated with this MC object device, if any.
181-
* @driver_override: driver name to force a match; do not set directly,
182-
* because core frees it; use driver_set_override() to
183-
* set or clear it.
184181
*
185182
* Generic device object for MC object devices that are "attached" to a
186183
* MC bus.
@@ -214,7 +211,6 @@ struct fsl_mc_device {
214211
struct fsl_mc_device_irq **irqs;
215212
struct fsl_mc_resource *resource;
216213
struct device_link *consumer_link;
217-
const char *driver_override;
218214
};
219215

220216
#define to_fsl_mc_device(_dev) \

0 commit comments

Comments
 (0)