DF-4977 / fix.diff
--- a/sys/dev/pccard/cardbus/cardbus.c 2026-09-25 14:18:13.549631345 +0000 +++ b/sys/dev/pccard/cardbus/cardbus.c 2026-09-25 14:18:13.573631032 +0000 @@ -224,6 +224,7 @@ device_t *devlist; int tmp; int err = 0; + int error; if (device_get_children(cbdev, &devlist, &numdevs) != 0) return (ENOENT); @@ -239,10 +240,30 @@ if (dinfo->pci.cfg.dev != devlist[tmp]) device_printf(cbdev, "devinfo dev mismatch\n"); - if (status == DS_ATTACHED || status == DS_BUSY) - device_detach(devlist[tmp]); + if (status == DS_ATTACHED || status == DS_BUSY) { + error = device_detach(devlist[tmp]); + if (error != 0) { + /* + * Child refuses to go away: keep both the + * child and its dinfo alive, else we free the + * ivars of a live device (UAF) and rip its + * resources out from under the driver. + */ + device_printf(cbdev, + "%s: child %s failed to detach (%d), " + "keeping its resources\n", __func__, + device_get_nameunit(devlist[tmp]), error); + err = error; + continue; + } + } cardbus_release_all_resources(cbdev, dinfo); - device_delete_child(cbdev, devlist[tmp]); + error = device_delete_child(cbdev, devlist[tmp]); + if (error != 0) { + /* child still exists and owns dinfo as its ivars */ + err = error; + continue; + } pci_freecfg((struct pci_devinfo *)dinfo); } POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); |