Skip to contentSkip to conversation

ata: pata_parport: KASAN slab-use-after-free in driver_find

BUG New Shuangpeng Bai 4 participants 5 messages Jul 28 – Jul 29

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Hi Kernel Maintainers,

I hit the following report while testing current upstream kernel:

KASAN: slab-use-after-free in driver_find

on commit: 62efbc768363bc7bb00f0915ad265f34b40d414e (2026-07-27)

To help trigger the bug more reliably, we applied a minimal diagnostic patch that only adds a delay.

The reproducer and .config files are here.
https://gist.github.com/shuangpengbai/a8a1b5339bc41944c2f80d9f87e01a7e

I'm happy to test debug patches or provide additional information.

[  755.753286][ T8297] BUG: KASAN: slab-use-after-free in driver_find (drivers/base/bus.c:1430)
[  755.754175][ T8297] Read of size 8 at addr ffff88812200f490 by task repro.sh/8297
[  755.755320][ T8297] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[  755.755331][ T8297] Call Trace:
[  755.755341][ T8297]  <TASK>
[  755.755344][ T8297]  dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[  755.755393][ T8297]  print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[  755.755478][ T8297]  kasan_report (mm/kasan/report.c:595)
[  755.755487][ T8297]  driver_find (drivers/base/bus.c:1430)
[  755.755502][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.755610][ T8297]  kernfs_fop_write_iter (fs/kernfs/file.c:345)
[  755.755615][ T8297]  vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[  755.755678][ T8297]  ksys_write (fs/read_write.c:739)
[  755.755703][ T8297]  do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[  755.755717][ T8297]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[  755.779923][ T8297] Freed by task 8297 on cpu 0 at 755.752571s:
[  755.780598][ T8297]  kasan_save_track (mm/kasan/common.c:57 mm/kasan/common.c:78)
[  755.781128][ T8297]  kasan_save_free_info (mm/kasan/generic.c:584)
[  755.781700][ T8297]  __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
[  755.782222][ T8297]  kfree (./include/linux/kasan.h:235 mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720)
[  755.782658][ T8297]  kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737)
[  755.783163][ T8297]  driver_find (drivers/base/bus.c:1429)
[  755.783659][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.787092][ T8297] The buggy address belongs to the object at ffff88812200f400
[  755.787092][ T8297]  which belongs to the cache kmalloc-192 of size 192
[  755.788598][ T8297] The buggy address is located 144 bytes inside of
[  755.788598][ T8297]  freed 192-byte region [ffff88812200f400, ffff88812200f4c0)

Best,
Shuangpeng

maintainer
#1 lore raw
Quoted 10 lines · Shuangpeng Bai

Hi Kernel Maintainers,

I hit the following report while testing current upstream kernel:

KASAN: slab-use-after-free in driver_find

on commit: 62efbc768363bc7bb00f0915ad265f34b40d414e (2026-07-27)

To help trigger the bug more reliably, we applied a minimal diagnostic patch that only adds a delay.

Can you share that patch/diff? That would make it easier to figure out where the race is because you are not describing anything here. The stack trace helps, but without being able to reproduce (I do not have the hardware), this will be hard to fix.

Quoted 2 lines

The reproducer and .config files are here.
https://gist.github.com/shuangpengbai/a8a1b5339bc41944c2f80d9f87e01a7e

This site has a broken certificate and Firefox does not want (rightly so) to get me there. So not touching this.

Quoted 35 lines

I'm happy to test debug patches or provide additional information.

[  755.753286][ T8297] BUG: KASAN: slab-use-after-free in driver_find (drivers/base/bus.c:1430)
[  755.754175][ T8297] Read of size 8 at addr ffff88812200f490 by task repro.sh/8297
[  755.755320][ T8297] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[  755.755331][ T8297] Call Trace:
[  755.755341][ T8297]  <TASK>
[  755.755344][ T8297]  dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[  755.755393][ T8297]  print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[  755.755478][ T8297]  kasan_report (mm/kasan/report.c:595)
[  755.755487][ T8297]  driver_find (drivers/base/bus.c:1430)
[  755.755502][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.755610][ T8297]  kernfs_fop_write_iter (fs/kernfs/file.c:345)
[  755.755615][ T8297]  vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[  755.755678][ T8297]  ksys_write (fs/read_write.c:739)
[  755.755703][ T8297]  do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[  755.755717][ T8297]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[  755.779923][ T8297] Freed by task 8297 on cpu 0 at 755.752571s:
[  755.780598][ T8297]  kasan_save_track (mm/kasan/common.c:57 mm/kasan/common.c:78)
[  755.781128][ T8297]  kasan_save_free_info (mm/kasan/generic.c:584)
[  755.781700][ T8297]  __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
[  755.782222][ T8297]  kfree (./include/linux/kasan.h:235 mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720)
[  755.782658][ T8297]  kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737)
[  755.783163][ T8297]  driver_find (drivers/base/bus.c:1429)
[  755.783659][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.787092][ T8297] The buggy address belongs to the object at ffff88812200f400
[  755.787092][ T8297]  which belongs to the cache kmalloc-192 of size 192
[  755.788598][ T8297] The buggy address is located 144 bytes inside of
[  755.788598][ T8297]  freed 192-byte region [ffff88812200f400, ffff88812200f4c0)

Best,
Shuangpeng

Signature · 2 lines
Damien Le Moal
Western Digital Research
author
#2 lore raw
Quoted 21 lines · Damien Le Moal
Quoted 10 lines · Shuangpeng Bai

Hi Kernel Maintainers,

I hit the following report while testing current upstream kernel:

KASAN: slab-use-after-free in driver_find

on commit: 62efbc768363bc7bb00f0915ad265f34b40d414e (2026-07-27)

To help trigger the bug more reliably, we applied a minimal diagnostic patch that only adds a delay.

Can you share that patch/diff? That would make it easier to figure out where the race is because you are not describing anything here. The stack trace helps, but without being able to reproduce (I do not have the hardware), this will be hard to fix.

Quoted 6 lines
Quoted 2 lines

The reproducer and .config files are here.
https://gist.github.com/shuangpengbai/a8a1b5339bc41944c2f80d9f87e01a7e

This site has a broken certificate and Firefox does not want (rightly so) to get me there. So not touching this.

Hi Damien,

Here are the reproducer details.

The diagnostic patch I used only widens the race window:

drivers/base/bus.c +3 -0
index d17bd91490ee..eb9dfbdd2aec 100644
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -1421,6 +1422,8 @@ struct device_driver *driver_find(const char *name, const struct bus_type *bus)
 		return NULL;
 
 	priv = to_driver(k);
+	if (!strcmp(name, "aten"))
+		msleep(200);
 
 	/* Drop reference added by kset_find_obj() */
 	kobject_put(k);

I reproduced this in QEMU, without parallel IDE hardware, using:

CONFIG_PARPORT_PC=y
CONFIG_PATA_PARPORT=y
CONFIG_PATA_PARPORT_ATEN=m
CONFIG_KASAN=y
CONFIG_DEBUG_KOBJECT_RELEASE=n

Then boot the kernel, make the in-tree ATEN protocol module available in the guest, and run:

  rmmod aten 2>/dev/null || true
  insmod ./aten.ko

(
echo "auto aten 0 0 0" > /sys/bus/pata_parport/new_device
) &

sleep 0.03
rmmod aten

With the delay above, this reliably triggers:

  KASAN: slab-use-after-free in driver_find

The relevant contract is the comment above driver_find(): it does not prevent the returned driver from being unregistered or unloaded while the caller uses it, and the caller is responsible for preventing that. In this case, new_device_store() calls driver_find() before taking pi_mutex, while pata_parport_unregister_driver() can remove the protocol and then unregister the driver concurrently.

Thanks,
Shuangpeng

Quoted 40 lines
Quoted 35 lines

I'm happy to test debug patches or provide additional information.

[  755.753286][ T8297] BUG: KASAN: slab-use-after-free in driver_find (drivers/base/bus.c:1430)
[  755.754175][ T8297] Read of size 8 at addr ffff88812200f490 by task repro.sh/8297
[  755.755320][ T8297] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[  755.755331][ T8297] Call Trace:
[  755.755341][ T8297]  <TASK>
[  755.755344][ T8297]  dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[  755.755393][ T8297]  print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[  755.755478][ T8297]  kasan_report (mm/kasan/report.c:595)
[  755.755487][ T8297]  driver_find (drivers/base/bus.c:1430)
[  755.755502][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.755610][ T8297]  kernfs_fop_write_iter (fs/kernfs/file.c:345)
[  755.755615][ T8297]  vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[  755.755678][ T8297]  ksys_write (fs/read_write.c:739)
[  755.755703][ T8297]  do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
[  755.755717][ T8297]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[  755.779923][ T8297] Freed by task 8297 on cpu 0 at 755.752571s:
[  755.780598][ T8297]  kasan_save_track (mm/kasan/common.c:57 mm/kasan/common.c:78)
[  755.781128][ T8297]  kasan_save_free_info (mm/kasan/generic.c:584)
[  755.781700][ T8297]  __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285)
[  755.782222][ T8297]  kfree (./include/linux/kasan.h:235 mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720)
[  755.782658][ T8297]  kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737)
[  755.783163][ T8297]  driver_find (drivers/base/bus.c:1429)
[  755.783659][ T8297]  new_device_store (drivers/ata/pata_parport/pata_parport.c:649)
[  755.787092][ T8297] The buggy address belongs to the object at ffff88812200f400
[  755.787092][ T8297]  which belongs to the cache kmalloc-192 of size 192
[  755.788598][ T8297] The buggy address is located 144 bytes inside of
[  755.788598][ T8297]  freed 192-byte region [ffff88812200f400, ffff88812200f4c0)

Best,
Shuangpeng

Signature · 2 lines
Damien Le Moal
Western Digital Research
#3 lore raw

PATCH 1/1 test: ata

hi maintainer and shuangpeng,

I tested this patch passed.

---
 drivers/ata/pata_parport/pata_parport.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/ata/pata_parport/pata_parport.c +4 -5
index 40baeac594a9..34f09192a419 100644
@@ -3,6 +3,7 @@
  * Copyright 2023 Ondrej Zary
  * based on paride.c by Grant R. Guenther <[email protected]>
  */
+#include <linux/cleanup.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/parport.h>
@@ -618,8 +619,9 @@ void pata_parport_unregister_driver(struct pi_protocol *pr)
 			break;
 	}
 	idr_remove(&protocols, id);
-	mutex_unlock(&pi_mutex);
 	driver_unregister(&pr->driver);
+	mutex_unlock(&pi_mutex);
+
 }
 EXPORT_SYMBOL_GPL(pata_parport_unregister_driver);
 
@@ -646,6 +648,7 @@ static ssize_t new_device_store(const struct bus_type *bus, const char *buf, siz
 		port_wanted = -1;
 	}
 
+	guard(mutex)(&pi_mutex);
 	drv = driver_find(protocol, &pata_parport_bus_type);
 	if (!drv) {
 		if (strcmp(protocol, "auto")) {
@@ -656,15 +659,12 @@ static ssize_t new_device_store(const struct bus_type *bus, const char *buf, siz
 	} else {
 		pr_wanted = container_of(drv, struct pi_protocol, driver);
 	}
-
-	mutex_lock(&pi_mutex);
 	/* walk all parports */
 	idr_for_each_entry(&parport_list, parport, port_num) {
 		if (port_num == port_wanted || port_wanted == -1) {
 			parport = parport_find_number(port_num);
 			if (!parport) {
 				pr_err("no such port %s\n", port);
-				mutex_unlock(&pi_mutex);
 				return -ENODEV;
 			}
 			/* walk all protocols */
@@ -677,7 +677,6 @@ static ssize_t new_device_store(const struct bus_type *bus, const char *buf, siz
 			parport_put_port(parport);
 		}
 	}
-	mutex_unlock(&pi_mutex);
 	if (!ok)
 		return -ENODEV;
 
Signature · 1 line
2.25.1
#4 lore raw

Re: [PATCH] test: ata

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] The commit message is completely devoid of technical details, failing to describe the changes, their purpose, or the problem being solved.

Pre-existing issues:
- [High] pata_parport_unregister_driver() does not unregister the devices associated with the unloaded protocol, leaving dangling devices on the bus that hold freed pointers. --

--- Patch [1]: [PATCH] test: ata ---
commit 787e1d65e64282ddc25d6c43593b6cd3674b9345
Author: Pei Xiao <[email protected]>

test: ata

This commit modifies locking in pata_parport by adopting guard(mutex) for pi_mutex in new_device_store() and extending the mutex_unlock call in pata_parport_unregister_driver() to also cover driver_unregister().

Quoted 5 lines

test: ata

hi maintainer and shuangpeng,

I tested this patch passed.

[Severity: Medium]
Could this commit message be expanded with more technical details?

The message only mentions that the patch was tested, but it does not describe the functional changes being introduced, such as expanding the lock scope to protect driver_find() and changing the lock ordering in the unregister path.

Describing the problem and the rationale for the changes would greatly assist with review and future maintenance.

Quoted 4 lines
drivers/ata/pata_parport/pata_parport.c +0 -0
index 40baeac594a9f..34f09192a4190 100644

[ ... ]

drivers/ata/pata_parport/pata_parport.c void pata_parport_unregister_driver(struct pi_protocol *pr) · line 625

Quoted 9 lines
drivers/ata/pata_parport/pata_parport.c +2 -1
@@ -618,8 +619,9 @@ void pata_parport_unregister_driver(struct pi_protocol *pr)
 			break;
 	}
 	idr_remove(&protocols, id);
-	mutex_unlock(&pi_mutex);
 	driver_unregister(&pr->driver);
+	mutex_unlock(&pi_mutex);
+
 }

[Severity: High]
This is a pre-existing issue, but does pata_parport_unregister_driver() leak devices?

When a protocol module's init function registers multiple protocols (like kbic_init registering k951 and k971) and a subsequent registration fails, it will call pata_parport_unregister_driver() on the already-registered protocol.

While the protocol is removed from the IDR and the driver is unregistered, the dynamically created pi_adapter devices are not cleaned up. Since the module init returns an error, the module loader frees the module memory, bypassing the reference held by the devices.

If these dangling devices are later removed (for example, via sysfs delete_device), pi_remove_one() calls pi_disconnect(pi), which dereferences the freed pi->proto->disconnect pointer, leading to a kernel crash.

Should the associated devices be unregistered here as well?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/170fe5b11ca8bffc32b4ec6588c289b29da11896.1785323372.git.xiaopei01@kylinos.cn?part=1