From: Cen Zhang <zzzccc427@gmail.com>
To: Jens Axboe <axboe@kernel.dk>, Kay Sievers <kay.sievers@vrfy.org>
Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
baijiaju1990@gmail.com, zzzccc427@gmail.com
Subject: [PATCH] loop: serialize backing file swaps with sysfs readers
Date: Wed, 24 Jun 2026 15:18:51 +0800 [thread overview]
Message-ID: <20260624071851.358250-1-zzzccc427@gmail.com> (raw)
The backing_file sysfs attribute formats lo->lo_backing_file while holding
lo_lock, but LOOP_CHANGE_FD replaced lo_backing_file without that lock.
The old file can then be fput() after the swap, and that fput may be the
last reference. This leaves a sysfs reader that observed the old pointer
able to run file_path() on a file whose final put is underway.
Validation reproduced this kernel report:
BUG: KCSAN: data-race in lo_ioctl / loop_attr_do_show_backing_file
The buggy scenario involves two paths, with each column showing the order
within that path:
sysfs backing_file show: LOOP_CHANGE_FD:
1. Take lo_lock. 1. Save old_file from lo_backing_file.
2. Read lo_backing_file. 2. Store the replacement file pointer.
3. Pass it to file_path(). 3. Drop the loop-owned old_file ref.
Serialize loop_assign_backing_file()'s pointer store with lo_lock, the
same lock used by the sysfs show path and by __loop_clr_fd(). This keeps a
sysfs reader that entered before the swap ordered before the old file can
be detached and fput(), and makes readers entering after the swap see the
new file.
Validation reproduced this kernel report:
[ 56.673265] BUG: KCSAN: data-race in lo_ioctl / loop_attr_do_show_backing_file
[ 56.674430] write to 0xffff888101d21060 of 8 bytes by task 498 on cpu 1:
[ 56.675365] lo_ioctl+0x99d/0xca0
[ 56.675819] blkdev_ioctl+0x2bc/0x380
[ 56.676331] __x64_sys_ioctl+0xc7/0x110
[ 56.676846] x64_sys_call+0x1092/0x1fb0
[ 56.677372] do_syscall_64+0x100/0x570
[ 56.677878] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 56.678777] read to 0xffff888101d21060 of 8 bytes by task 489 on cpu 2:
[ 56.679617] loop_attr_do_show_backing_file+0x51/0xe0
[ 56.680280] dev_attr_show+0x3b/0x90
[ 56.680769] sysfs_kf_seq_show+0x139/0x1e0
[ 56.681321] kernfs_seq_show+0x9c/0xb0
[ 56.681823] seq_read_iter+0x2b3/0x830
[ 56.682336] kernfs_fop_read_iter+0x26b/0x2d0
[ 56.682917] vfs_read+0x414/0x5c0
[ 56.683393] ksys_read+0xa3/0x130
[ 56.683844] __x64_sys_read+0x41/0x50
[ 56.684344] x64_sys_call+0x1efb/0x1fb0
[ 56.684856] do_syscall_64+0x100/0x570
[ 56.685364] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 56.686252] value changed: 0xffff888104d62900 -> 0xffff888104d53680
[ 56.687275] Reported by Kernel Concurrency Sanitizer on:
[ 56.687963] CPU: 2 UID: 0 PID: 489 Comm: loop_changefd_r Not tainted 7.1.0-02794-g5c7804e3279c #1 PREEMPT(lazy)
[ 56.689251] 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
[ 56.690673] ==================================================================
[ 62.334003] ==================================================================
[ 62.334986] BUG: KCSAN: data-race in lo_ioctl / loop_attr_do_show_backing_file
[ 62.336145] write to 0xffff888101d21060 of 8 bytes by task 498 on cpu 3:
[ 62.337000] lo_ioctl+0x99d/0xca0
[ 62.337452] blkdev_ioctl+0x2bc/0x380
[ 62.337955] __x64_sys_ioctl+0xc7/0x110
[ 62.338468] x64_sys_call+0x1092/0x1fb0
[ 62.338993] do_syscall_64+0x100/0x570
[ 62.339493] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 62.340381] read to 0xffff888101d21060 of 8 bytes by task 495 on cpu 0:
[ 62.341235] loop_attr_do_show_backing_file+0x51/0xe0
[ 62.341900] dev_attr_show+0x3b/0x90
[ 62.342385] sysfs_kf_seq_show+0x139/0x1e0
[ 62.342943] kernfs_seq_show+0x9c/0xb0
[ 62.343447] seq_read_iter+0x2b3/0x830
[ 62.343955] kernfs_fop_read_iter+0x26b/0x2d0
[ 62.344537] vfs_read+0x414/0x5c0
[ 62.344988] ksys_read+0xa3/0x130
[ 62.345438] __x64_sys_read+0x41/0x50
[ 62.345937] x64_sys_call+0x1efb/0x1fb0
[ 62.346446] do_syscall_64+0x100/0x570
[ 62.346956] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 62.347832] value changed: 0xffff888104d50f00 -> 0xffff888104cf4f00
[ 62.348871] Reported by Kernel Concurrency Sanitizer on:
[ 62.349548] CPU: 0 UID: 0 PID: 495 Comm: loop_changefd_r Not tainted 7.1.0-02794-g5c7804e3279c #1 PREEMPT(lazy)
[ 62.350823] 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
[ 62.352260] ==================================================================
[ 65.676721] ==================================================================
[ 65.677703] BUG: KCSAN: data-race in lo_ioctl / loop_attr_do_show_backing_file
[ 65.678870] write to 0xffff888101d21060 of 8 bytes by task 498 on cpu 0:
[ 65.679712] lo_ioctl+0x99d/0xca0
[ 65.680166] blkdev_ioctl+0x2bc/0x380
[ 65.680673] __x64_sys_ioctl+0xc7/0x110
[ 65.681187] x64_sys_call+0x1092/0x1fb0
[ 65.681707] do_syscall_64+0x100/0x570
[ 65.682214] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 65.683113] read to 0xffff888101d21060 of 8 bytes by task 497 on cpu 2:
[ 65.683955] loop_attr_do_show_backing_file+0x51/0xe0
[ 65.684617] dev_attr_show+0x3b/0x90
[ 65.685109] sysfs_kf_seq_show+0x139/0x1e0
[ 65.685663] kernfs_seq_show+0x9c/0xb0
[ 65.686165] seq_read_iter+0x2b3/0x830
[ 65.686679] kernfs_fop_read_iter+0x26b/0x2d0
[ 65.687265] vfs_read+0x414/0x5c0
[ 65.687720] ksys_read+0xa3/0x130
[ 65.688171] __x64_sys_read+0x41/0x50
[ 65.688665] x64_sys_call+0x1efb/0x1fb0
[ 65.689177] do_syscall_64+0x100/0x570
[ 65.689688] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 65.690582] value changed: 0xffff888100c52600 -> 0xffff888104d54180
[ 65.691615] Reported by Kernel Concurrency Sanitizer on:
[ 65.692309] CPU: 2 UID: 0 PID: 497 Comm: loop_changefd_r Not tainted 7.1.0-02794-g5c7804e3279c #1 PREEMPT(lazy)
[ 65.693596] 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
[ 65.695035] ==================================================================
[ 68.697953] ==================================================================
[ 68.698927] BUG: KCSAN: data-race in lo_ioctl / loop_attr_do_show_backing_file
[ 68.700101] write to 0xffff888101d21060 of 8 bytes by task 498 on cpu 1:
Fixes: 05eb0f252b04 ("loop: fix deadlock when sysfs and LOOP_CLR_FD race against each other")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---
drivers/block/loop.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 310de0463beb..45937741fcb6 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -503,11 +503,18 @@ static int loop_validate_file(struct file *file, struct block_device *bdev)
static void loop_assign_backing_file(struct loop_device *lo, struct file *file)
{
+ /*
+ * Serialize the pointer update with sysfs backing_file show, which
+ * formats the file path under lo_lock without taking a file reference.
+ */
+ spin_lock_irq(&lo->lo_lock);
lo->lo_backing_file = file;
+ spin_unlock_irq(&lo->lo_lock);
+
lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
mapping_set_gfp_mask(file->f_mapping,
lo->old_gfp_mask & ~(__GFP_IO | __GFP_FS));
- if (lo->lo_backing_file->f_flags & O_DIRECT)
+ if (file->f_flags & O_DIRECT)
lo->lo_flags |= LO_FLAGS_DIRECT_IO;
lo->lo_min_dio_size = loop_query_min_dio_size(lo);
}
--
2.43.0
reply other threads:[~2026-06-24 7:18 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260624071851.358250-1-zzzccc427@gmail.com \
--to=zzzccc427@gmail.com \
--cc=axboe@kernel.dk \
--cc=baijiaju1990@gmail.com \
--cc=kay.sievers@vrfy.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox