* [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get()
@ 2026-10-07 21:15 Dingisoul
2026-10-12 20:17 ` Dingisoul
0 siblings, 1 reply; 5+ messages in thread
From: Dingisoul @ 2026-10-07 21:15 UTC (permalink / raw)
To: James E . J . Bottomley, Martin K . Petersen; +Cc: linux-scsi, linux-kernel
Hi Kernel Maintainers,
I hit the following report while testing current upstream kernel:
KASAN: slab-use-after-free in st_open
on commit: a90ee4305c4a (2026-10-06)
Root cause: st_remove() does
mutex_lock(&st_ref_mutex);
kref_put(&tpnt->kref, scsi_tape_release); /* may kfree(tpnt) here */
mutex_unlock(&st_ref_mutex);
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, index); /* too late: already freed above */
spin_unlock(&st_index_lock);
while scsi_tape_get() (called from st_open() on every open of a tape
device node) does
mutex_lock(&st_ref_mutex);
spin_lock(&st_index_lock);
STp = idr_find(&st_index_idr, dev); /* can still find the freed tpnt */
kref_get(&STp->kref); /* UAF write */
There is a window, between st_remove()'s mutex_unlock() and its own
spin_lock(), where a concurrent scsi_tape_get() can acquire both locks
and find the already-freed tpnt still in st_index_idr.
To help trigger the bug more reliably, we applied a minimal diagnostic
patch that only inserts a fixed udelay(2000) in that window (no locks
added/removed, no reordering); it does not change the bug itself. We used
scsi_debug (ptype=1, emulating a tape LUN) to avoid needing real tape
hardware.
The reproducer and .config files are here.
https://gist.github.com/dingiso/b33f8c01a47bfcbb902d3f21a4877feb
I'm happy to test debug patches or provide additional information.
[ 23.212502] ==================================================================
[ 23.212506] BUG: KASAN: slab-use-after-free in st_open (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:252 ./include/linux/refcount.h:283 ./include/linux/refcount.h:366 ./include/linux/refcount.h:383 ./include/linux/kref.h:45 drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
[ 23.212537] Write of size 4 at addr ffff888009854a1c by task repro/315
[ 23.212541]
[ 23.212551] 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
[ 23.212554] Call Trace:
[ 23.212556] <TASK>
[ 23.212558] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 23.212566] print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[ 23.212591] kasan_report (mm/kasan/report.c:595)
[ 23.212602] kasan_check_range (mm/kasan/generic.c:186 mm/kasan/generic.c:200)
[ 23.212607] st_open (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:252 ./include/linux/refcount.h:283 ./include/linux/refcount.h:366 ./include/linux/refcount.h:383 ./include/linux/kref.h:45 drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
[ 23.212623] chrdev_open (fs/char_dev.c:411)
[ 23.212645] do_dentry_open (fs/open.c:996)
[ 23.212651] vfs_open (fs/open.c:1101)
[ 23.212656] path_openat (fs/namei.c:4837 fs/namei.c:5000)
[ 23.212669] do_file_open (fs/namei.c:5029)
[ 23.212693] do_sys_openat2 (fs/open.c:1417 (discriminator 1))
[ 23.212702] __x64_sys_openat (fs/open.c:1423 fs/open.c:1439 fs/open.c:1434 fs/open.c:1434)
[ 23.212712] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 23.212719] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 23.212755]
[ 23.212756] Allocated by task 325:
[ 23.212758] kasan_save_stack (mm/kasan/common.c:57)
[ 23.212764] kasan_save_track (mm/kasan/common.c:78)
[ 23.212768] __kasan_kmalloc (mm/kasan/common.c:409 mm/kasan/common.c:426)
[ 23.212773] __kmalloc_cache_noprof (./include/linux/kasan.h:263 mm/slub.c:5563)
[ 23.212778] st_probe (./include/linux/slab.h:991 ./include/linux/slab.h:1312 drivers/scsi/st.c:4376)
[ 23.212783] really_probe (drivers/base/dd.c:628 drivers/base/dd.c:706)
[ 23.212788] __driver_probe_device (drivers/base/dd.c:868)
[ 23.212793] driver_probe_device (drivers/base/dd.c:898)
[ 23.212798] __device_attach_driver (drivers/base/dd.c:1026)
[ 23.212803] bus_for_each_drv (drivers/base/bus.c:500)
[ 23.212807] __device_attach (drivers/base/dd.c:1098)
[ 23.212811] device_initial_probe (drivers/base/dd.c:1153)
[ 23.212816] bus_probe_device (drivers/base/bus.c:620)
[ 23.212821] device_add (drivers/base/core.c:3776)
[ 23.212826] scsi_sysfs_add_sdev (drivers/scsi/scsi_sysfs.c:1427)
[ 23.212830] scsi_add_lun (drivers/scsi/scsi_scan.c:1138 (discriminator 1))
[ 23.212834] scsi_probe_and_add_lun (drivers/scsi/scsi_scan.c:1311)
[ 23.212838] __scsi_scan_target (drivers/scsi/scsi_scan.c:1805)
[ 23.212841] scsi_scan_channel (drivers/scsi/scsi_scan.c:1895 drivers/scsi/scsi_scan.c:1870)
[ 23.212845] scsi_scan_host_selected (drivers/scsi/scsi_scan.c:1924)
[ 23.212849] scsi_scan_host (drivers/scsi/scsi_scan.c:2089 drivers/scsi/scsi_scan.c:2077)
[ 23.212852] sdebug_driver_probe (drivers/scsi/scsi_debug.c:9618) scsi_debug
[ 23.212875] really_probe (drivers/base/dd.c:628 drivers/base/dd.c:706)
[ 23.212879] __driver_probe_device (drivers/base/dd.c:868)
[ 23.212883] driver_probe_device (drivers/base/dd.c:898)
[ 23.212887] __device_attach_driver (drivers/base/dd.c:1026)
[ 23.212891] bus_for_each_drv (drivers/base/bus.c:500)
[ 23.212895] __device_attach (drivers/base/dd.c:1098)
[ 23.212900] device_initial_probe (drivers/base/dd.c:1153)
[ 23.212905] bus_probe_device (drivers/base/bus.c:620)
[ 23.212909] device_add (drivers/base/core.c:3776)
[ 23.212914] sdebug_add_host_helper (drivers/scsi/scsi_debug.c:8843) scsi_debug
[ 23.212937] add_host_store (drivers/scsi/scsi_debug.c:8878 drivers/scsi/scsi_debug.c:8105) scsi_debug
[ 23.212954] kernfs_fop_write_iter (fs/kernfs/file.c:345)
[ 23.212960] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[ 23.212964] ksys_write (fs/read_write.c:739)
[ 23.212968] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 23.212973] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 23.212977]
[ 23.212978] Freed by task 325:
[ 23.212980] kasan_save_stack (mm/kasan/common.c:57)
[ 23.212984] kasan_save_track (mm/kasan/common.c:78)
[ 23.212989] kasan_save_free_info (mm/kasan/generic.c:584)
[ 23.212993] __kasan_slab_free (mm/kasan/common.c:264 mm/kasan/common.c:296)
[ 23.212997] kfree (./include/linux/kasan.h:235 mm/slub.c:2748 mm/slub.c:6509 mm/slub.c:6802)
[ 23.213000] st_remove (./include/linux/kref.h:65 drivers/scsi/st.c:4512)
[ 23.213004] device_release_driver_internal (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
[ 23.213009] bus_remove_device (drivers/base/bus.c:664)
[ 23.213014] device_del (drivers/base/core.c:3965)
[ 23.213018] __scsi_remove_device (drivers/scsi/scsi_sysfs.c:1499)
[ 23.213021] scsi_forget_host (drivers/scsi/scsi_scan.c:2115)
[ 23.213025] scsi_remove_host (drivers/scsi/hosts.c:182)
[ 23.213031] sdebug_driver_remove (drivers/scsi/scsi_debug.c:9631) scsi_debug
[ 23.213052] device_release_driver_internal (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
[ 23.213057] bus_remove_device (drivers/base/bus.c:664)
[ 23.213061] device_del (drivers/base/core.c:3965)
[ 23.213065] device_unregister (drivers/base/core.c:4006)
[ 23.213070] sdebug_do_remove_host (drivers/scsi/scsi_debug.c:8917) scsi_debug
[ 23.213089] add_host_store (drivers/scsi/scsi_debug.c:8110) scsi_debug
[ 23.213109] kernfs_fop_write_iter (fs/kernfs/file.c:345)
[ 23.213113] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[ 23.213117] ksys_write (fs/read_write.c:739)
[ 23.213121] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 23.213126] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
Best,
Dingisoul
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get()
2026-10-07 21:15 [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get() Dingisoul
@ 2026-10-12 20:17 ` Dingisoul
2026-10-13 12:52 ` Laurence Oberman
0 siblings, 1 reply; 5+ messages in thread
From: Dingisoul @ 2026-10-12 20:17 UTC (permalink / raw)
To: dingiso.kernel; +Cc: James.Bottomley, linux-kernel, linux-scsi, mkp, loberman
Hi Laurence,
Adding you to Cc as requested. Quoting the original report below for
reference; let me know if you'd like anything else re-tested.
Best,
Dingisoul
> Hi Kernel Maintainers,
>
> I hit the following report while testing current upstream kernel:
>
> KASAN: slab-use-after-free in st_open
>
> on commit: a90ee4305c4a (2026-10-06)
>
> Root cause: st_remove() drops the device's last reference, and only
> afterwards removes it from st_index_idr:
>
> static void st_remove(struct scsi_device *SDp)
> {
> struct device *dev = &SDp->sdev_gendev;
> struct scsi_tape *tpnt = dev_get_drvdata(dev);
> int index = tpnt->index;
> ...
> mutex_lock(&st_ref_mutex);
> kref_put(&tpnt->kref, scsi_tape_release); /* may kfree(tpnt) right here */
> mutex_unlock(&st_ref_mutex);
> spin_lock(&st_index_lock);
> idr_remove(&st_index_idr, index); /* too late: tpnt may already be freed */
> spin_unlock(&st_index_lock);
> }
>
> Meanwhile scsi_tape_get() -- called from st_open() on every open of a
> tape device node -- looks the device up by the same index and takes its
> own reference:
>
> static struct scsi_tape *scsi_tape_get(int dev)
> {
> struct scsi_tape *STp = NULL;
>
> mutex_lock(&st_ref_mutex);
> spin_lock(&st_index_lock);
>
> STp = idr_find(&st_index_idr, dev); /* can still find the freed tpnt */
> if (!STp) goto out;
>
> kref_get(&STp->kref); /* UAF write */
> ...
> }
>
> static int st_open(struct inode *inode, struct file *filp)
> {
> ...
> if (!(STp = scsi_tape_get(dev))) {
> ...
>
> Between st_remove()'s mutex_unlock(&st_ref_mutex) and its own
> spin_lock(&st_index_lock), tpnt is already freed but still reachable
> through st_index_idr. A concurrent st_open() racing in that window takes
> both locks in scsi_tape_get(), finds the stale idr entry, and calls
> kref_get() on the freed tpnt.
>
> We used scsi_debug (ptype=1, emulating a tape LUN) to avoid needing real
> tape hardware.
>
> The reproducer and .config files are here.
> https://gist.github.com/dingiso/b33f8c01a47bfcbb902d3f21a4877feb
>
> I'm happy to test debug patches or provide additional information.
>
> [ 23.212502] ==================================================================
> [ 23.212506] BUG: KASAN: slab-use-after-free in st_open (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:252 ./include/linux/refcount.h:283 ./include/linux/refcount.h:366 ./include/linux/refcount.h:383 ./include/linux/kref.h:45 drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
> [ 23.212537] Write of size 4 at addr ffff888009854a1c by task repro/315
> [ 23.212541]
> [ 23.212551] 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
> [ 23.212554] Call Trace:
> [ 23.212556] <TASK>
> [ 23.212558] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
> [ 23.212566] print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
> [ 23.212591] kasan_report (mm/kasan/report.c:595)
> [ 23.212602] kasan_check_range (mm/kasan/generic.c:186 mm/kasan/generic.c:200)
> [ 23.212607] st_open (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:252 ./include/linux/refcount.h:283 ./include/linux/refcount.h:366 ./include/linux/refcount.h:383 ./include/linux/kref.h:45 drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
> [ 23.212623] chrdev_open (fs/char_dev.c:411)
> [ 23.212645] do_dentry_open (fs/open.c:996)
> [ 23.212651] vfs_open (fs/open.c:1101)
> [ 23.212656] path_openat (fs/namei.c:4837 fs/namei.c:5000)
> [ 23.212669] do_file_open (fs/namei.c:5029)
> [ 23.212693] do_sys_openat2 (fs/open.c:1417 (discriminator 1))
> [ 23.212702] __x64_sys_openat (fs/open.c:1423 fs/open.c:1439 fs/open.c:1434 fs/open.c:1434)
> [ 23.212712] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
> [ 23.212719] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> [ 23.212755]
> [ 23.212756] Allocated by task 325:
> [ 23.212758] kasan_save_stack (mm/kasan/common.c:57)
> [ 23.212764] kasan_save_track (mm/kasan/common.c:78)
> [ 23.212768] __kasan_kmalloc (mm/kasan/common.c:409 mm/kasan/common.c:426)
> [ 23.212773] __kmalloc_cache_noprof (./include/linux/kasan.h:263 mm/slub.c:5563)
> [ 23.212778] st_probe (./include/linux/slab.h:991 ./include/linux/slab.h:1312 drivers/scsi/st.c:4376)
> [ 23.212783] really_probe (drivers/base/dd.c:628 drivers/base/dd.c:706)
> [ 23.212788] __driver_probe_device (drivers/base/dd.c:868)
> [ 23.212793] driver_probe_device (drivers/base/dd.c:898)
> [ 23.212798] __device_attach_driver (drivers/base/dd.c:1026)
> [ 23.212803] bus_for_each_drv (drivers/base/bus.c:500)
> [ 23.212807] __device_attach (drivers/base/dd.c:1098)
> [ 23.212811] device_initial_probe (drivers/base/dd.c:1153)
> [ 23.212816] bus_probe_device (drivers/base/bus.c:620)
> [ 23.212821] device_add (drivers/base/core.c:3776)
> [ 23.212826] scsi_sysfs_add_sdev (drivers/scsi/scsi_sysfs.c:1427)
> [ 23.212830] scsi_add_lun (drivers/scsi/scsi_scan.c:1138 (discriminator 1))
> [ 23.212834] scsi_probe_and_add_lun (drivers/scsi/scsi_scan.c:1311)
> [ 23.212838] __scsi_scan_target (drivers/scsi/scsi_scan.c:1805)
> [ 23.212841] scsi_scan_channel (drivers/scsi/scsi_scan.c:1895 drivers/scsi/scsi_scan.c:1870)
> [ 23.212845] scsi_scan_host_selected (drivers/scsi/scsi_scan.c:1924)
> [ 23.212849] scsi_scan_host (drivers/scsi/scsi_scan.c:2089 drivers/scsi/scsi_scan.c:2077)
> [ 23.212852] sdebug_driver_probe (drivers/scsi/scsi_debug.c:9618) scsi_debug
> [ 23.212875] really_probe (drivers/base/dd.c:628 drivers/base/dd.c:706)
> [ 23.212879] __driver_probe_device (drivers/base/dd.c:868)
> [ 23.212883] driver_probe_device (drivers/base/dd.c:898)
> [ 23.212887] __device_attach_driver (drivers/base/dd.c:1026)
> [ 23.212891] bus_for_each_drv (drivers/base/bus.c:500)
> [ 23.212895] __device_attach (drivers/base/dd.c:1098)
> [ 23.212900] device_initial_probe (drivers/base/dd.c:1153)
> [ 23.212905] bus_probe_device (drivers/base/bus.c:620)
> [ 23.212909] device_add (drivers/base/core.c:3776)
> [ 23.212914] sdebug_add_host_helper (drivers/scsi/scsi_debug.c:8843) scsi_debug
> [ 23.212937] add_host_store (drivers/scsi/scsi_debug.c:8878 drivers/scsi/scsi_debug.c:8105) scsi_debug
> [ 23.212954] kernfs_fop_write_iter (fs/kernfs/file.c:345)
> [ 23.212960] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
> [ 23.212964] ksys_write (fs/read_write.c:739)
> [ 23.212968] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
> [ 23.212973] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> [ 23.212977]
> [ 23.212978] Freed by task 325:
> [ 23.212980] kasan_save_stack (mm/kasan/common.c:57)
> [ 23.212984] kasan_save_track (mm/kasan/common.c:78)
> [ 23.212989] kasan_save_free_info (mm/kasan/generic.c:584)
> [ 23.212993] __kasan_slab_free (mm/kasan/common.c:264 mm/kasan/common.c:296)
> [ 23.212997] kfree (./include/linux/kasan.h:235 mm/slub.c:2748 mm/slub.c:6509 mm/slub.c:6802)
> [ 23.213000] st_remove (./include/linux/kref.h:65 drivers/scsi/st.c:4512)
> [ 23.213004] device_release_driver_internal (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
> [ 23.213009] bus_remove_device (drivers/base/bus.c:664)
> [ 23.213014] device_del (drivers/base/core.c:3965)
> [ 23.213018] __scsi_remove_device (drivers/scsi/scsi_sysfs.c:1499)
> [ 23.213021] scsi_forget_host (drivers/scsi/scsi_scan.c:2115)
> [ 23.213025] scsi_remove_host (drivers/scsi/hosts.c:182)
> [ 23.213031] sdebug_driver_remove (drivers/scsi/scsi_debug.c:9631) scsi_debug
> [ 23.213052] device_release_driver_internal (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
> [ 23.213057] bus_remove_device (drivers/base/bus.c:664)
> [ 23.213061] device_del (drivers/base/core.c:3965)
> [ 23.213065] device_unregister (drivers/base/core.c:4006)
> [ 23.213070] sdebug_do_remove_host (drivers/scsi/scsi_debug.c:8917) scsi_debug
> [ 23.213089] add_host_store (drivers/scsi/scsi_debug.c:8110) scsi_debug
> [ 23.213109] kernfs_fop_write_iter (fs/kernfs/file.c:345)
> [ 23.213113] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
> [ 23.213117] ksys_write (fs/read_write.c:739)
> [ 23.213121] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
> [ 23.213126] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
> Best,
> Dingisoul
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get()
2026-10-12 20:17 ` Dingisoul
@ 2026-10-13 12:52 ` Laurence Oberman
2026-10-13 20:01 ` Dingisoul
0 siblings, 1 reply; 5+ messages in thread
From: Laurence Oberman @ 2026-10-13 12:52 UTC (permalink / raw)
To: Dingisoul; +Cc: James.Bottomley, linux-kernel, linux-scsi, mkp
On Mon, 2026-10-12 at 16:17 -0400, Dingisoul wrote:
> Hi Laurence,
>
> Adding you to Cc as requested. Quoting the original report below for
> reference; let me know if you'd like anything else re-tested.
>
> Best,
> Dingisoul
>
> > Hi Kernel Maintainers,
> >
> > I hit the following report while testing current upstream kernel:
> >
> > KASAN: slab-use-after-free in st_open
> >
> > on commit: a90ee4305c4a (2026-10-06)
> >
> > Root cause: st_remove() drops the device's last reference, and only
> > afterwards removes it from st_index_idr:
> >
> > static void st_remove(struct scsi_device *SDp)
> > {
> > struct device *dev = &SDp->sdev_gendev;
> > struct scsi_tape *tpnt = dev_get_drvdata(dev);
> > int index = tpnt->index;
> > ...
> > mutex_lock(&st_ref_mutex);
> > kref_put(&tpnt->kref, scsi_tape_release); /* may
> > kfree(tpnt) right here */
> > mutex_unlock(&st_ref_mutex);
> > spin_lock(&st_index_lock);
> > idr_remove(&st_index_idr, index); /* too late:
> > tpnt may already be freed */
> > spin_unlock(&st_index_lock);
> > }
> >
> > Meanwhile scsi_tape_get() -- called from st_open() on every open of
> > a
> > tape device node -- looks the device up by the same index and takes
> > its
> > own reference:
> >
> > static struct scsi_tape *scsi_tape_get(int dev)
> > {
> > struct scsi_tape *STp = NULL;
> >
> > mutex_lock(&st_ref_mutex);
> > spin_lock(&st_index_lock);
> >
> > STp = idr_find(&st_index_idr, dev); /* can still find the
> > freed tpnt */
> > if (!STp) goto out;
> >
> > kref_get(&STp->kref); /* UAF write */
> > ...
> > }
> >
> > static int st_open(struct inode *inode, struct file *filp)
> > {
> > ...
> > if (!(STp = scsi_tape_get(dev))) {
> > ...
> >
> > Between st_remove()'s mutex_unlock(&st_ref_mutex) and its own
> > spin_lock(&st_index_lock), tpnt is already freed but still
> > reachable
> > through st_index_idr. A concurrent st_open() racing in that window
> > takes
> > both locks in scsi_tape_get(), finds the stale idr entry, and calls
> > kref_get() on the freed tpnt.
> >
> > We used scsi_debug (ptype=1, emulating a tape LUN) to avoid needing
> > real
> > tape hardware.
> >
> > The reproducer and .config files are here.
> > https://gist.github.com/dingiso/b33f8c01a47bfcbb902d3f21a4877feb
> >
> > I'm happy to test debug patches or provide additional information.
> >
> > [ 23.212502]
> > ==================================================================
> > [ 23.212506] BUG: KASAN: slab-use-after-free in st_open
> > (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-
> > instrumented.h:252 ./include/linux/refcount.h:283
> > ./include/linux/refcount.h:366 ./include/linux/refcount.h:383
> > ./include/linux/kref.h:45 drivers/scsi/st.c:254
> > drivers/scsi/st.c:1291)
> > [ 23.212537] Write of size 4 at addr ffff888009854a1c by task
> > repro/315
> > [ 23.212541]
> > [ 23.212551] 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
> > [ 23.212554] Call Trace:
> > [ 23.212556] <TASK>
> > [ 23.212558] dump_stack_lvl (lib/dump_stack.c:94
> > lib/dump_stack.c:120)
> > [ 23.212566] print_report (mm/kasan/report.c:378
> > mm/kasan/report.c:482)
> > [ 23.212591] kasan_report (mm/kasan/report.c:595)
> > [ 23.212602] kasan_check_range (mm/kasan/generic.c:186
> > mm/kasan/generic.c:200)
> > [ 23.212607] st_open (./include/linux/instrumented.h:112
> > ./include/linux/atomic/atomic-instrumented.h:252
> > ./include/linux/refcount.h:283 ./include/linux/refcount.h:366
> > ./include/linux/refcount.h:383 ./include/linux/kref.h:45
> > drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
> > [ 23.212623] chrdev_open (fs/char_dev.c:411)
> > [ 23.212645] do_dentry_open (fs/open.c:996)
> > [ 23.212651] vfs_open (fs/open.c:1101)
> > [ 23.212656] path_openat (fs/namei.c:4837 fs/namei.c:5000)
> > [ 23.212669] do_file_open (fs/namei.c:5029)
> > [ 23.212693] do_sys_openat2 (fs/open.c:1417 (discriminator 1))
> > [ 23.212702] __x64_sys_openat (fs/open.c:1423 fs/open.c:1439
> > fs/open.c:1434 fs/open.c:1434)
> > [ 23.212712] do_syscall_64 (arch/x86/entry/syscall_64.c:61
> > arch/x86/entry/syscall_64.c:84)
> > [ 23.212719] entry_SYSCALL_64_after_hwframe
> > (arch/x86/entry/entry_64.S:121)
> > [ 23.212755]
> > [ 23.212756] Allocated by task 325:
> > [ 23.212758] kasan_save_stack (mm/kasan/common.c:57)
> > [ 23.212764] kasan_save_track (mm/kasan/common.c:78)
> > [ 23.212768] __kasan_kmalloc (mm/kasan/common.c:409
> > mm/kasan/common.c:426)
> > [ 23.212773] __kmalloc_cache_noprof (./include/linux/kasan.h:263
> > mm/slub.c:5563)
> > [ 23.212778] st_probe (./include/linux/slab.h:991
> > ./include/linux/slab.h:1312 drivers/scsi/st.c:4376)
> > [ 23.212783] really_probe (drivers/base/dd.c:628
> > drivers/base/dd.c:706)
> > [ 23.212788] __driver_probe_device (drivers/base/dd.c:868)
> > [ 23.212793] driver_probe_device (drivers/base/dd.c:898)
> > [ 23.212798] __device_attach_driver (drivers/base/dd.c:1026)
> > [ 23.212803] bus_for_each_drv (drivers/base/bus.c:500)
> > [ 23.212807] __device_attach (drivers/base/dd.c:1098)
> > [ 23.212811] device_initial_probe (drivers/base/dd.c:1153)
> > [ 23.212816] bus_probe_device (drivers/base/bus.c:620)
> > [ 23.212821] device_add (drivers/base/core.c:3776)
> > [ 23.212826] scsi_sysfs_add_sdev
> > (drivers/scsi/scsi_sysfs.c:1427)
> > [ 23.212830] scsi_add_lun (drivers/scsi/scsi_scan.c:1138
> > (discriminator 1))
> > [ 23.212834] scsi_probe_and_add_lun
> > (drivers/scsi/scsi_scan.c:1311)
> > [ 23.212838] __scsi_scan_target (drivers/scsi/scsi_scan.c:1805)
> > [ 23.212841] scsi_scan_channel (drivers/scsi/scsi_scan.c:1895
> > drivers/scsi/scsi_scan.c:1870)
> > [ 23.212845] scsi_scan_host_selected
> > (drivers/scsi/scsi_scan.c:1924)
> > [ 23.212849] scsi_scan_host (drivers/scsi/scsi_scan.c:2089
> > drivers/scsi/scsi_scan.c:2077)
> > [ 23.212852] sdebug_driver_probe (drivers/scsi/scsi_debug.c:9618)
> > scsi_debug
> > [ 23.212875] really_probe (drivers/base/dd.c:628
> > drivers/base/dd.c:706)
> > [ 23.212879] __driver_probe_device (drivers/base/dd.c:868)
> > [ 23.212883] driver_probe_device (drivers/base/dd.c:898)
> > [ 23.212887] __device_attach_driver (drivers/base/dd.c:1026)
> > [ 23.212891] bus_for_each_drv (drivers/base/bus.c:500)
> > [ 23.212895] __device_attach (drivers/base/dd.c:1098)
> > [ 23.212900] device_initial_probe (drivers/base/dd.c:1153)
> > [ 23.212905] bus_probe_device (drivers/base/bus.c:620)
> > [ 23.212909] device_add (drivers/base/core.c:3776)
> > [ 23.212914] sdebug_add_host_helper
> > (drivers/scsi/scsi_debug.c:8843) scsi_debug
> > [ 23.212937] add_host_store (drivers/scsi/scsi_debug.c:8878
> > drivers/scsi/scsi_debug.c:8105) scsi_debug
> > [ 23.212954] kernfs_fop_write_iter (fs/kernfs/file.c:345)
> > [ 23.212960] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
> > [ 23.212964] ksys_write (fs/read_write.c:739)
> > [ 23.212968] do_syscall_64 (arch/x86/entry/syscall_64.c:61
> > arch/x86/entry/syscall_64.c:84)
> > [ 23.212973] entry_SYSCALL_64_after_hwframe
> > (arch/x86/entry/entry_64.S:121)
> > [ 23.212977]
> > [ 23.212978] Freed by task 325:
> > [ 23.212980] kasan_save_stack (mm/kasan/common.c:57)
> > [ 23.212984] kasan_save_track (mm/kasan/common.c:78)
> > [ 23.212989] kasan_save_free_info (mm/kasan/generic.c:584)
> > [ 23.212993] __kasan_slab_free (mm/kasan/common.c:264
> > mm/kasan/common.c:296)
> > [ 23.212997] kfree (./include/linux/kasan.h:235 mm/slub.c:2748
> > mm/slub.c:6509 mm/slub.c:6802)
> > [ 23.213000] st_remove (./include/linux/kref.h:65
> > drivers/scsi/st.c:4512)
> > [ 23.213004] device_release_driver_internal
> > (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
> > [ 23.213009] bus_remove_device (drivers/base/bus.c:664)
> > [ 23.213014] device_del (drivers/base/core.c:3965)
> > [ 23.213018] __scsi_remove_device
> > (drivers/scsi/scsi_sysfs.c:1499)
> > [ 23.213021] scsi_forget_host (drivers/scsi/scsi_scan.c:2115)
> > [ 23.213025] scsi_remove_host (drivers/scsi/hosts.c:182)
> > [ 23.213031] sdebug_driver_remove
> > (drivers/scsi/scsi_debug.c:9631) scsi_debug
> > [ 23.213052] device_release_driver_internal
> > (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
> > [ 23.213057] bus_remove_device (drivers/base/bus.c:664)
> > [ 23.213061] device_del (drivers/base/core.c:3965)
> > [ 23.213065] device_unregister (drivers/base/core.c:4006)
> > [ 23.213070] sdebug_do_remove_host
> > (drivers/scsi/scsi_debug.c:8917) scsi_debug
> > [ 23.213089] add_host_store (drivers/scsi/scsi_debug.c:8110)
> > scsi_debug
> > [ 23.213109] kernfs_fop_write_iter (fs/kernfs/file.c:345)
> > [ 23.213113] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
> > [ 23.213117] ksys_write (fs/read_write.c:739)
> > [ 23.213121] do_syscall_64 (arch/x86/entry/syscall_64.c:61
> > arch/x86/entry/syscall_64.c:84)
> > [ 23.213126] entry_SYSCALL_64_after_hwframe
> > (arch/x86/entry/entry_64.S:121)
> > Best,
> > Dingisoul
Hello
Please try this patch, let me know if it fixes this and I will send a
follow up to finalize this fix.
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f1c3c49466..d5b90bd1c6 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4509,11 +4509,11 @@ static void st_remove(struct scsi_device *SDp)
remove_cdevs(tpnt);
mutex_lock(&st_ref_mutex);
- kref_put(&tpnt->kref, scsi_tape_release);
- mutex_unlock(&st_ref_mutex);
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, index);
spin_unlock(&st_index_lock);
+ kref_put(&tpnt->kref, scsi_tape_release);
+ mutex_unlock(&st_ref_mutex);
}
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get()
2026-10-13 12:52 ` Laurence Oberman
@ 2026-10-13 20:01 ` Dingisoul
2026-10-13 20:25 ` [PATCH] scsi: st: Fix use-after-free race between st_remove() and st_open() loberman
0 siblings, 1 reply; 5+ messages in thread
From: Dingisoul @ 2026-10-13 20:01 UTC (permalink / raw)
To: loberman; +Cc: James.Bottomley, dingiso.kernel, linux-kernel, linux-scsi, mkp
Hi Laurence,
Applied your patch, rebuilt, and reran the original reproducer.
No KASAN report, no warnings, no panic across the whole run.
Looks good to me -- feel free to send it upstream.
Best,
Dingisoul
On your patch:
> Hello
>
> Please try this patch, let me know if it fixes this and I will send a
> follow up to finalize this fix.
>
>
> diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
> index f1c3c49466..d5b90bd1c6 100644
> --- a/drivers/scsi/st.c
> +++ b/drivers/scsi/st.c
> @@ -4509,11 +4509,11 @@ static void st_remove(struct scsi_device *SDp)
> remove_cdevs(tpnt);
>
> mutex_lock(&st_ref_mutex);
> - kref_put(&tpnt->kref, scsi_tape_release);
> - mutex_unlock(&st_ref_mutex);
> spin_lock(&st_index_lock);
> idr_remove(&st_index_idr, index);
> spin_unlock(&st_index_lock);
> + kref_put(&tpnt->kref, scsi_tape_release);
> + mutex_unlock(&st_ref_mutex);
> }
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] scsi: st: Fix use-after-free race between st_remove() and st_open()
2026-10-13 20:01 ` Dingisoul
@ 2026-10-13 20:25 ` loberman
0 siblings, 0 replies; 5+ messages in thread
From: loberman @ 2026-10-13 20:25 UTC (permalink / raw)
To: linux-scsi, martin.petersen
Cc: James.Bottomley, Kai.Makisara, jmeneghi, dingiso.kernel,
Laurence Oberman, stable
From: Laurence Oberman <loberman@redhat.com>
st_remove() drops the probe reference on the scsi_tape with kref_put()
and only afterwards removes its index from st_index_idr. If that was the
last reference, scsi_tape_release() frees the structure while it is
still published in the idr.
scsi_tape_get(), called from st_open(), looks up the tape in
st_index_idr and takes a reference under st_ref_mutex and
st_index_lock. remove_cdevs() does not wait for opens that are already
past chrdev_open(), so an open that is blocked on st_ref_mutex while
st_remove() holds it can take the mutex as soon as st_remove() drops
it, find the freed tpnt in the idr and call kref_get() on it:
BUG: KASAN: slab-use-after-free in st_open
Write of size 4 ...
st_open (drivers/scsi/st.c:254 drivers/scsi/st.c:1291)
chrdev_open
...
Freed by task ...:
kfree
st_remove (drivers/scsi/st.c:4512)
Remove the index from the idr before dropping the reference, all under
st_ref_mutex. A concurrent scsi_tape_get() now either runs first and
holds a valid reference that keeps the tape alive, or runs afterwards
and finds nothing, so st_open() fails with -ENXIO.
This restores the ordering st_remove() had before the conversion to
st_index_idr, where the tape was unpublished from scsi_tapes[] before
the final kref_put().
Fixes: 6c648d95a6af ("[SCSI] st: get rid of scsi_tapes array")
Cc: stable@vger.kernel.org
Reported-by: Dingisoul <dingiso.kernel@gmail.com>
Closes: https://lore.kernel.org/linux-scsi/20261007211520.1428497-1-dingiso.kernel@gmail.com/
Tested-by: Dingisoul <dingiso.kernel@gmail.com>
Signed-off-by: Laurence Oberman <loberman@redhat.com>
---
drivers/scsi/st.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index f1c3c4946637..d5b90bd1c6dc 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4509,11 +4509,11 @@ static void st_remove(struct scsi_device *SDp)
remove_cdevs(tpnt);
mutex_lock(&st_ref_mutex);
- kref_put(&tpnt->kref, scsi_tape_release);
- mutex_unlock(&st_ref_mutex);
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, index);
spin_unlock(&st_index_lock);
+ kref_put(&tpnt->kref, scsi_tape_release);
+ mutex_unlock(&st_ref_mutex);
}
/**
--
2.56.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-13 20:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-07 21:15 [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get() Dingisoul
2026-10-12 20:17 ` Dingisoul
2026-10-13 12:52 ` Laurence Oberman
2026-10-13 20:01 ` Dingisoul
2026-10-13 20:25 ` [PATCH] scsi: st: Fix use-after-free race between st_remove() and st_open() loberman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.