From: Dingisoul <dingiso.kernel@gmail.com>
To: dingiso.kernel@gmail.com
Cc: James.Bottomley@HansenPartnership.com,
linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org,
mkp@kernel.org, loberman@redhat.com
Subject: Re: [BUG] scsi: st: use-after-free race between st_remove() and st_open()/scsi_tape_get()
Date: Mon, 12 Oct 2026 16:17:30 -0400 [thread overview]
Message-ID: <20261012201730.1853897-1-dingiso.kernel@gmail.com> (raw)
In-Reply-To: <20261007211520.1428497-1-dingiso.kernel@gmail.com>
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
next prev parent reply other threads:[~2026-10-12 20:17 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261012201730.1853897-1-dingiso.kernel@gmail.com \
--to=dingiso.kernel@gmail.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=loberman@redhat.com \
--cc=mkp@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.