Skip to content

Commit 8139ce6

Browse files
Danilo Krummrichgregkh
authored andcommitted
bus: fsl-mc: use generic driver_override infrastructure
[ Upstream commit 6c8dfb0 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 2081957 commit 8139ce6

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;
@@ -181,39 +185,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
181185
}
182186
static DEVICE_ATTR_RO(modalias);
183187

184-
static ssize_t driver_override_store(struct device *dev,
185-
struct device_attribute *attr,
186-
const char *buf, size_t count)
187-
{
188-
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
189-
int ret;
190-
191-
if (WARN_ON(dev->bus != &fsl_mc_bus_type))
192-
return -EINVAL;
193-
194-
ret = driver_set_override(dev, &mc_dev->driver_override, buf, count);
195-
if (ret)
196-
return ret;
197-
198-
return count;
199-
}
200-
201-
static ssize_t driver_override_show(struct device *dev,
202-
struct device_attribute *attr, char *buf)
203-
{
204-
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
205-
ssize_t len;
206-
207-
device_lock(dev);
208-
len = sysfs_emit(buf, "%s\n", mc_dev->driver_override);
209-
device_unlock(dev);
210-
return len;
211-
}
212-
static DEVICE_ATTR_RW(driver_override);
213-
214188
static struct attribute *fsl_mc_dev_attrs[] = {
215189
&dev_attr_modalias.attr,
216-
&dev_attr_driver_override.attr,
217190
NULL,
218191
};
219192

@@ -316,6 +289,7 @@ ATTRIBUTE_GROUPS(fsl_mc_bus);
316289

317290
const struct bus_type fsl_mc_bus_type = {
318291
.name = "fsl-mc",
292+
.driver_override = true,
319293
.match = fsl_mc_bus_match,
320294
.uevent = fsl_mc_bus_uevent,
321295
.dma_configure = fsl_mc_dma_configure,
@@ -925,9 +899,6 @@ static struct notifier_block fsl_mc_nb;
925899
*/
926900
void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
927901
{
928-
kfree(mc_dev->driver_override);
929-
mc_dev->driver_override = NULL;
930-
931902
/*
932903
* The device-specific remove callback will get invoked by device_del()
933904
*/

drivers/vfio/fsl-mc/vfio_fsl_mc.c

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

431431
if (action == BUS_NOTIFY_ADD_DEVICE &&
432432
vdev->mc_dev == mc_cont) {
433-
mc_dev->driver_override = kasprintf(GFP_KERNEL, "%s",
434-
vfio_fsl_mc_ops.name);
435-
if (!mc_dev->driver_override)
433+
if (device_set_driver_override(dev, vfio_fsl_mc_ops.name))
436434
dev_warn(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s failed\n",
437435
dev_name(&mc_cont->dev));
438436
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)