[PATCH 2/2] ata: pata_parport: unregister devices on protocol unregister

From: Pei Xiao

Date: Wed Sep 02 2026 - 08:07:17 EST


When a protocol module registers multiple protocols and a later
registration fails (e.g. kbic_init registering k951 then k971), the
rollback path calls pata_parport_unregister_driver() on the already
registered protocol. This removes the protocol from the IDR and
unregisters the driver, but leaves the dynamically created pi_adapter
devices untouched.

Since the module init then fails, the module loader frees the module
memory, bypassing the references held by the devices. Any later removal
of these dangling devices (e.g. via sysfs delete_device or parport
detach) hits pi_remove_one() -> pi_disconnect() -> pi->proto->disconnect,
dereferencing the freed module memory and crashing the kernel.

Tear down all pi_adapters using the protocol in
pata_parport_unregister_driver(), before driver_unregister(), while the
module is still alive so the ->disconnect / ->release_proto callbacks
are safe to call.

Fixes: 246a1c4c6b7f ("ata: pata_parport: add driver (PARIDE replacement)")
Signed-off-by: Pei Xiao <xiaopei01@xxxxxxxxxx>
---
drivers/ata/pata_parport/pata_parport.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c
index 7462f9b1acc5..4ee518807031 100644
--- a/drivers/ata/pata_parport/pata_parport.c
+++ b/drivers/ata/pata_parport/pata_parport.c
@@ -612,6 +612,18 @@ int pata_parport_register_driver(struct pi_protocol *pr)
}
EXPORT_SYMBOL_GPL(pata_parport_register_driver);

+static int pi_remove_by_proto(struct device *dev, void *data)
+{
+ struct pi_protocol *pr = data;
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct pi_adapter *pi = host->private_data;
+
+ if (pi->proto == pr)
+ pi_remove_one(dev);
+
+ return 0;
+}
+
void pata_parport_unregister_driver(struct pi_protocol *pr)
{
struct pi_protocol *pr_iter;
@@ -623,6 +635,8 @@ void pata_parport_unregister_driver(struct pi_protocol *pr)
break;
}
idr_remove(&protocols, id);
+ /* remove adapters using this protocol while the module is still alive */
+ bus_for_each_dev(&pata_parport_bus_type, NULL, pr, pi_remove_by_proto);
driver_unregister(&pr->driver);
mutex_unlock(&pi_mutex);

--
2.25.1