* [PATCH 0/2] ata: pata_parport: fix UAF on protocol module unload
@ 2026-09-02 11:50 Pei Xiao
2026-09-02 11:50 ` [PATCH 1/2] ata: pata_parport: pin the protocol module before device_register() Pei Xiao
2026-09-02 11:50 ` [PATCH 2/2] ata: pata_parport: unregister devices on protocol unregister Pei Xiao
0 siblings, 2 replies; 3+ messages in thread
From: Pei Xiao @ 2026-09-02 11:50 UTC (permalink / raw)
To: dlemoal, cassel, linux-ide, linux-kernel; +Cc: shuangpeng.kernel, Pei Xiao
This series fixes use-after-free issues in pata_parport when a protocol
module goes away while pi_adapter devices created by it are still
attached.
Patch 1 pins the protocol module before the device becomes visible.
Previously try_module_get() ran after device_register(), so a forced
module unload in between left pi->proto dangling from the moment the
device appeared on the bus.
Patch 2 makes pata_parport_unregister_driver() tear down all adapters
using the protocol. Without this, the rollback path of a multi-protocol
module init (e.g. kbic registering k951 then k971) left the devices of
the already-registered protocol alive while the module loader freed the
module memory; removing such a dangling device later crashed in
pi_disconnect() dereferencing pi->proto->disconnect.
Pei Xiao (2):
ata: pata_parport: pin the protocol module before device_register()
ata: pata_parport: unregister devices on protocol unregister
drivers/ata/pata_parport/pata_parport.c | 27 +++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/2] ata: pata_parport: pin the protocol module before device_register()
2026-09-02 11:50 [PATCH 0/2] ata: pata_parport: fix UAF on protocol module unload Pei Xiao
@ 2026-09-02 11:50 ` Pei Xiao
2026-09-02 11:50 ` [PATCH 2/2] ata: pata_parport: unregister devices on protocol unregister Pei Xiao
1 sibling, 0 replies; 3+ messages in thread
From: Pei Xiao @ 2026-09-02 11:50 UTC (permalink / raw)
To: dlemoal, cassel, linux-ide, linux-kernel; +Cc: shuangpeng.kernel, Pei Xiao
pi_init_one() calls device_register() before try_module_get(). Between
these two calls the device is already visible but the module is not
pinned yet, so an unload in this window leaves pi->proto dangling:
pi_init_one() rmmod -f <proto>
--------------------------------------------------------
device_register(&pi->dev)
device visible on the bus
module memory freed
pi->proto = pr <- writes into freed memory / dangles
try_module_get(...) <- too late, module already gone
Take the module reference before registering the device, and drop it
on the device_register() failure path.
Fixes: 246a1c4c6b7f ("ata: pata_parport: add driver (PARIDE replacement)")
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
---
drivers/ata/pata_parport/pata_parport.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c
index cf81a6128f55..7462f9b1acc5 100644
--- a/drivers/ata/pata_parport/pata_parport.c
+++ b/drivers/ata/pata_parport/pata_parport.c
@@ -509,6 +509,14 @@ static struct pi_adapter *pi_init_one(struct parport *parport,
return NULL;
}
+ pi->proto = pr;
+
+ if (!try_module_get(pi->proto->owner)) {
+ kfree(pi);
+ ida_free(&pata_parport_bus_dev_ids, id);
+ return NULL;
+ }
+
/* set up pi->dev before pi_probe_unit() so it can use dev_printk() */
pi->dev.parent = pata_parport_bus;
pi->dev.bus = &pata_parport_bus_type;
@@ -517,15 +525,12 @@ static struct pi_adapter *pi_init_one(struct parport *parport,
pi->dev.id = id;
dev_set_name(&pi->dev, "pata_parport.%u", pi->dev.id);
if (device_register(&pi->dev)) {
+ module_put(pi->proto->owner);
put_device(&pi->dev);
/* pata_parport_dev_release will do ida_free(dev->id) and kfree(pi) */
return NULL;
}
- pi->proto = pr;
-
- if (!try_module_get(pi->proto->owner))
- goto out_unreg_dev;
if (pi->proto->init_proto && pi->proto->init_proto(pi) < 0)
goto out_module_put;
--
2.25.1
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 2/2] ata: pata_parport: unregister devices on protocol unregister
2026-09-02 11:50 [PATCH 0/2] ata: pata_parport: fix UAF on protocol module unload Pei Xiao
2026-09-02 11:50 ` [PATCH 1/2] ata: pata_parport: pin the protocol module before device_register() Pei Xiao
@ 2026-09-02 11:50 ` Pei Xiao
1 sibling, 0 replies; 3+ messages in thread
From: Pei Xiao @ 2026-09-02 11:50 UTC (permalink / raw)
To: dlemoal, cassel, linux-ide, linux-kernel; +Cc: shuangpeng.kernel, Pei Xiao
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@kylinos.cn>
---
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
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-02 11:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-02 11:50 [PATCH 0/2] ata: pata_parport: fix UAF on protocol module unload Pei Xiao
2026-09-02 11:50 ` [PATCH 1/2] ata: pata_parport: pin the protocol module before device_register() Pei Xiao
2026-09-02 11:50 ` [PATCH 2/2] ata: pata_parport: unregister devices on protocol unregister Pei Xiao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®