Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 1f86a00c1159 ("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>

+8 -43
+7 -36
drivers/bus/fsl-mc/fsl-mc-bus.c
··· 86 86 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 87 87 const struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv); 88 88 bool found = false; 89 + int ret; 89 90 90 91 /* 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; 93 95 goto out; 94 96 } 97 + if (ret == 0) 98 + goto out; 95 99 96 100 if (!mc_drv->match_id_table) 97 101 goto out; ··· 214 210 } 215 211 static DEVICE_ATTR_RO(modalias); 216 212 217 - static ssize_t driver_override_store(struct device *dev, 218 - struct device_attribute *attr, 219 - const char *buf, size_t count) 220 - { 221 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 222 - int ret; 223 - 224 - if (WARN_ON(dev->bus != &fsl_mc_bus_type)) 225 - return -EINVAL; 226 - 227 - ret = driver_set_override(dev, &mc_dev->driver_override, buf, count); 228 - if (ret) 229 - return ret; 230 - 231 - return count; 232 - } 233 - 234 - static ssize_t driver_override_show(struct device *dev, 235 - struct device_attribute *attr, char *buf) 236 - { 237 - struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); 238 - ssize_t len; 239 - 240 - device_lock(dev); 241 - len = sysfs_emit(buf, "%s\n", mc_dev->driver_override); 242 - device_unlock(dev); 243 - return len; 244 - } 245 - static DEVICE_ATTR_RW(driver_override); 246 - 247 213 static struct attribute *fsl_mc_dev_attrs[] = { 248 214 &dev_attr_modalias.attr, 249 - &dev_attr_driver_override.attr, 250 215 NULL, 251 216 }; 252 217 ··· 318 345 319 346 const struct bus_type fsl_mc_bus_type = { 320 347 .name = "fsl-mc", 348 + .driver_override = true, 321 349 .match = fsl_mc_bus_match, 322 350 .uevent = fsl_mc_bus_uevent, 323 351 .probe = fsl_mc_probe, ··· 884 910 */ 885 911 void fsl_mc_device_remove(struct fsl_mc_device *mc_dev) 886 912 { 887 - kfree(mc_dev->driver_override); 888 - mc_dev->driver_override = NULL; 889 - 890 913 /* 891 914 * The device-specific remove callback will get invoked by device_del() 892 915 */
+1 -3
drivers/vfio/fsl-mc/vfio_fsl_mc.c
··· 424 424 425 425 if (action == BUS_NOTIFY_ADD_DEVICE && 426 426 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)) 430 428 dev_warn(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s failed\n", 431 429 dev_name(&mc_cont->dev)); 432 430 else
-4
include/linux/fsl/mc.h
··· 178 178 * @regions: pointer to array of MMIO region entries 179 179 * @irqs: pointer to array of pointers to interrupts allocated to this device 180 180 * @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. 184 181 * 185 182 * Generic device object for MC object devices that are "attached" to a 186 183 * MC bus. ··· 211 214 struct fsl_mc_device_irq **irqs; 212 215 struct fsl_mc_resource *resource; 213 216 struct device_link *consumer_link; 214 - const char *driver_override; 215 217 }; 216 218 217 219 #define to_fsl_mc_device(_dev) \