* [syzbot] [fs?] possible deadlock in ovl_create_object (2)
@ 2026-09-09 15:19 syzbot
2026-09-12 13:12 ` syzbot
` (2 more replies)
0 siblings, 3 replies; 25+ messages in thread
From: syzbot @ 2026-09-09 15:19 UTC (permalink / raw)
To: dakr, driver-core, gregkh, linux-fsdevel, linux-kernel, rafael,
syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 654ae5d73c05 Merge tag 'drm-fixes-2026-09-05' of https://g..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=11860cf9580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f
dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00
compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
Unfortunately, I don't have any reproducer for this issue yet.
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/90a1eb1b2bfe/disk-654ae5d7.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/dcbbe9cf09c5/vmlinux-654ae5d7.xz
kernel image: https://storage.googleapis.com/syzbot-assets/c80eca6821dd/bzImage-654ae5d7.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com
======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Tainted: G L
------------------------------------------------------
syz.6.857/9678 is trying to acquire lock:
ffff88803cd16460 (sb_writers#6){.+.+}-{0:0}, at: ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705
but task is already holding lock:
ffff888058c6e948 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: inode_lock include/linux/fs.h:1024 [inline]
ffff888058c6e948 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: lookup_open+0xb13/0x1990 fs/namei.c:4458
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #4 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}:
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
down_read+0x99/0x4c0 kernel/locking/rwsem.c:1574
inode_lock_shared include/linux/fs.h:1039 [inline]
lookup_slow+0x42/0x70 fs/namei.c:1935
walk_component fs/namei.c:2282 [inline]
lookup_last fs/namei.c:2789 [inline]
path_lookupat+0x5e8/0xc40 fs/namei.c:2813
filename_lookup+0x202/0x590 fs/namei.c:2842
kern_path+0x37/0x50 fs/namei.c:3036
lookup_bdev+0xd8/0x2a0 block/bdev.c:1268
bdev_file_open_by_path+0x82/0x330 block/bdev.c:1123
add_device drivers/mtd/devices/block2mtd.c:279 [inline]
block2mtd_setup2.isra.0+0x2ee/0xbd0 drivers/mtd/devices/block2mtd.c:459
block2mtd_setup+0xbd/0xd0 drivers/mtd/devices/block2mtd.c:476
param_attr_store+0x199/0x300 kernel/params.c:591
module_attr_store+0x58/0x80 kernel/params.c:906
sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145
kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345
new_sync_write fs/read_write.c:595 [inline]
vfs_write+0x6af/0x1050 fs/read_write.c:687
ksys_write+0x12a/0x250 fs/read_write.c:739
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #3 (param_lock){+.+.}-{4:4}:
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821
ieee80211_rate_control_ops_get net/mac80211/rate.c:221 [inline]
rate_control_alloc net/mac80211/rate.c:267 [inline]
ieee80211_init_rate_ctrl_alg+0x1df/0x3b0 net/mac80211/rate.c:1008
ieee80211_register_hw+0x2c1e/0x4580 net/mac80211/main.c:1561
mac80211_hwsim_new_radio+0x2b08/0x6510 drivers/net/wireless/virtual/mac80211_hwsim_main.c:6138
init_mac80211_hwsim+0x5e2/0x6f0 drivers/net/wireless/virtual/mac80211_hwsim_main.c:7624
do_one_initcall+0x11c/0x6f0 init/main.c:1357
do_initcall_level init/main.c:1419 [inline]
do_initcalls init/main.c:1435 [inline]
do_basic_setup init/main.c:1455 [inline]
kernel_init_freeable+0x6ea/0x7b0 init/main.c:1670
kernel_init+0x21/0x1e0 init/main.c:1560
ret_from_fork+0x730/0xd60 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
-> #2 (rtnl_mutex){+.+.}-{4:4}:
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821
rtnl_lock net/core/rtnetlink.c:80 [inline]
rtnetlink_rcv_msg+0x371/0xe90 net/core/rtnetlink.c:7138
netlink_rcv_skb+0x159/0x420 net/netlink/af_netlink.c:2556
netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
netlink_unicast+0x585/0x850 net/netlink/af_netlink.c:1345
netlink_sendmsg+0x8b0/0xda0 net/netlink/af_netlink.c:1900
sock_sendmsg_nosec net/socket.c:800 [inline]
__sock_sendmsg net/socket.c:815 [inline]
sock_sendmsg+0x394/0x410 net/socket.c:838
splice_to_socket+0xb3c/0x11a0 fs/splice.c:884
do_splice_from fs/splice.c:936 [inline]
do_splice+0x109c/0x1fa0 fs/splice.c:1349
__do_splice+0x33b/0x370 fs/splice.c:1431
__do_sys_splice fs/splice.c:1634 [inline]
__se_sys_splice fs/splice.c:1616 [inline]
__x64_sys_splice+0x187/0x250 fs/splice.c:1616
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #1 (&pipe->mutex){+.+.}-{4:4}:
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821
pipe_lock fs/pipe.c:91 [inline]
pipe_lock+0x69/0x80 fs/pipe.c:88
iter_file_splice_write+0x1fd/0x10b0 fs/splice.c:682
do_splice_from fs/splice.c:936 [inline]
do_splice+0x109c/0x1fa0 fs/splice.c:1349
__do_splice+0x33b/0x370 fs/splice.c:1431
__do_sys_splice fs/splice.c:1634 [inline]
__se_sys_splice fs/splice.c:1616 [inline]
__x64_sys_splice+0x187/0x250 fs/splice.c:1616
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #0 (sb_writers#6){.+.+}-{0:0}:
check_prev_add+0xeb/0xe60 kernel/locking/lockdep.c:3181
check_prevs_add kernel/locking/lockdep.c:3300 [inline]
validate_chain kernel/locking/lockdep.c:3924 [inline]
__lock_acquire+0x1492/0x1ec0 kernel/locking/lockdep.c:5254
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline]
percpu_down_read_freezable include/linux/percpu-rwsem.h:83 [inline]
__sb_start_write include/linux/fs/super.h:19 [inline]
sb_start_write include/linux/fs/super.h:125 [inline]
mnt_want_write+0x6f/0x420 fs/namespace.c:494
ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705
lookup_open+0x1255/0x1990 fs/namei.c:4567
open_last_lookups fs/namei.c:4767 [inline]
path_openat+0xa2c/0x2440 fs/namei.c:4997
do_file_open+0x20e/0x430 fs/namei.c:5029
do_sys_openat2+0x10f/0x1e0 fs/open.c:1417
do_sys_open fs/open.c:1423 [inline]
__do_sys_openat fs/open.c:1439 [inline]
__se_sys_openat fs/open.c:1434 [inline]
__x64_sys_openat+0x12d/0x210 fs/open.c:1434
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
other info that might help us debug this:
Chain exists of:
sb_writers#6 --> param_lock --> &ovl_i_mutex_dir_key[depth]
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&ovl_i_mutex_dir_key[depth]);
lock(param_lock);
lock(&ovl_i_mutex_dir_key[depth]);
rlock(sb_writers#6);
*** DEADLOCK ***
locks held by syz.6.857/9678: 2, last CPU#1:
#0: ffff88802ba66460 (sb_writers#13){.+.+}-{0:0}, at: lookup_open+0x150/0x1990 fs/namei.c:4451
#1: ffff888058c6e948 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: inode_lock include/linux/fs.h:1024 [inline]
#1: ffff888058c6e948 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: lookup_open+0xb13/0x1990 fs/namei.c:4458
stack backtrace:
CPU: 1 UID: 0 PID: 9678 Comm: syz.6.857 Tainted: G L syzkaller #0 PREEMPT(full)
Tainted: [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/05/2026
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120
print_circular_bug.cold+0x178/0x1be kernel/locking/lockdep.c:2059
check_noncircular+0x146/0x160 kernel/locking/lockdep.c:2191
check_prev_add+0xeb/0xe60 kernel/locking/lockdep.c:3181
check_prevs_add kernel/locking/lockdep.c:3300 [inline]
validate_chain kernel/locking/lockdep.c:3924 [inline]
__lock_acquire+0x1492/0x1ec0 kernel/locking/lockdep.c:5254
lock_acquire kernel/locking/lockdep.c:5908 [inline]
lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5865
percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline]
percpu_down_read_freezable include/linux/percpu-rwsem.h:83 [inline]
__sb_start_write include/linux/fs/super.h:19 [inline]
sb_start_write include/linux/fs/super.h:125 [inline]
mnt_want_write+0x6f/0x420 fs/namespace.c:494
ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705
lookup_open+0x1255/0x1990 fs/namei.c:4567
open_last_lookups fs/namei.c:4767 [inline]
path_openat+0xa2c/0x2440 fs/namei.c:4997
do_file_open+0x20e/0x430 fs/namei.c:5029
do_sys_openat2+0x10f/0x1e0 fs/open.c:1417
do_sys_open fs/open.c:1423 [inline]
__do_sys_openat fs/open.c:1439 [inline]
__se_sys_openat fs/open.c:1434 [inline]
__x64_sys_openat+0x12d/0x210 fs/open.c:1434
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2d2539e159
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f2d261d2028 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
RAX: ffffffffffffffda RBX: 00007f2d25625fa0 RCX: 00007f2d2539e159
RDX: 0000000000000040 RSI: 0000200000000180 RDI: ffffffffffffff9c
RBP: 00007f2d25435024 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000023 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f2d25626038 R14: 00007f2d25625fa0 R15: 00007ffeef1e4b18
</TASK>
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-09 15:19 [syzbot] [fs?] possible deadlock in ovl_create_object (2) syzbot @ 2026-09-12 13:12 ` syzbot 2026-09-16 19:48 ` Chris Roy 2026-09-20 18:51 ` [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write Chris Roy 2 siblings, 0 replies; 25+ messages in thread From: syzbot @ 2026-09-12 13:12 UTC (permalink / raw) To: dakr, driver-core, gregkh, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs syzbot has found a reproducer for the following issue on: HEAD commit: 5225b8eec4c9 mailmap: update entry for Jens Axboe git tree: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git console output: https://syzkaller.appspot.com/x/log.txt?x=104c82d1580000 kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=144c82d1580000 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com block2mtd: error: cannot open device /tmp/ovl_bug_7ivaQs/merged/nonexistent ====================================================== WARNING: possible circular locking dependency detected syzkaller #0 Not tainted ------------------------------------------------------ syz-executor469/6041 is trying to acquire lock: ffff888024d8c460 (sb_writers#6){.+.+}-{0:0}, at: ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705 but task is already holding lock: ffff88805802a7a8 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: inode_lock include/linux/fs.h:1024 [inline] ffff88805802a7a8 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: lookup_open+0xb13/0x1990 fs/namei.c:4458 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #4 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}: lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 down_read+0x99/0x4c0 kernel/locking/rwsem.c:1574 inode_lock_shared include/linux/fs.h:1039 [inline] lookup_slow+0x42/0x70 fs/namei.c:1935 walk_component fs/namei.c:2282 [inline] lookup_last fs/namei.c:2789 [inline] path_lookupat+0x5e8/0xc40 fs/namei.c:2813 filename_lookup+0x202/0x590 fs/namei.c:2842 kern_path+0x37/0x50 fs/namei.c:3036 lookup_bdev+0xd8/0x2a0 block/bdev.c:1268 bdev_file_open_by_path+0x82/0x330 block/bdev.c:1123 add_device drivers/mtd/devices/block2mtd.c:279 [inline] block2mtd_setup2.isra.0+0x2ee/0xbd0 drivers/mtd/devices/block2mtd.c:459 block2mtd_setup+0xbd/0xd0 drivers/mtd/devices/block2mtd.c:476 param_attr_store+0x199/0x300 kernel/params.c:591 module_attr_store+0x58/0x80 kernel/params.c:906 sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 do_splice_from fs/splice.c:936 [inline] do_splice+0x109c/0x1fa0 fs/splice.c:1349 __do_splice+0x33b/0x370 fs/splice.c:1431 __do_sys_splice fs/splice.c:1634 [inline] __se_sys_splice fs/splice.c:1616 [inline] __x64_sys_splice+0x187/0x250 fs/splice.c:1616 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #3 (param_lock){+.+.}-{4:4}: lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 __mutex_lock_common kernel/locking/mutex.c:646 [inline] __mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821 kernel_param_lock kernel/params.c:604 [inline] param_attr_store+0xec/0x300 kernel/params.c:589 module_attr_store+0x58/0x80 kernel/params.c:906 sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 new_sync_write fs/read_write.c:595 [inline] vfs_write+0x6af/0x1050 fs/read_write.c:687 ksys_write+0x12a/0x250 fs/read_write.c:739 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #2 (&of->mutex){+.+.}-{4:4}: lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 __mutex_lock_common kernel/locking/mutex.c:646 [inline] __mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821 kernfs_fop_write_iter+0x2c2/0x5f0 fs/kernfs/file.c:336 iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 do_splice_from fs/splice.c:936 [inline] do_splice+0x109c/0x1fa0 fs/splice.c:1349 __do_splice+0x33b/0x370 fs/splice.c:1431 __do_sys_splice fs/splice.c:1634 [inline] __se_sys_splice fs/splice.c:1616 [inline] __x64_sys_splice+0x187/0x250 fs/splice.c:1616 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #1 (&pipe->mutex){+.+.}-{4:4}: lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 __mutex_lock_common kernel/locking/mutex.c:646 [inline] __mutex_lock+0x1a4/0x1bd0 kernel/locking/mutex.c:821 pipe_lock fs/pipe.c:91 [inline] pipe_lock+0x69/0x80 fs/pipe.c:88 iter_file_splice_write+0x1fd/0x10b0 fs/splice.c:682 do_splice_from fs/splice.c:936 [inline] do_splice+0x109c/0x1fa0 fs/splice.c:1349 __do_splice+0x33b/0x370 fs/splice.c:1431 __do_sys_splice fs/splice.c:1634 [inline] __se_sys_splice fs/splice.c:1616 [inline] __x64_sys_splice+0x187/0x250 fs/splice.c:1616 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #0 (sb_writers#6){.+.+}-{0:0}: check_prev_add+0xeb/0xe60 kernel/locking/lockdep.c:3209 check_prevs_add kernel/locking/lockdep.c:3328 [inline] validate_chain kernel/locking/lockdep.c:3952 [inline] __lock_acquire+0x1528/0x1f40 kernel/locking/lockdep.c:5288 lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline] percpu_down_read_freezable include/linux/percpu-rwsem.h:83 [inline] __sb_start_write include/linux/fs/super.h:19 [inline] sb_start_write include/linux/fs/super.h:125 [inline] mnt_want_write+0x6f/0x420 fs/namespace.c:494 ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705 lookup_open+0x1255/0x1990 fs/namei.c:4567 open_last_lookups fs/namei.c:4767 [inline] path_openat+0xa2c/0x2440 fs/namei.c:4997 do_file_open+0x20e/0x430 fs/namei.c:5029 do_sys_openat2+0x10f/0x1e0 fs/open.c:1417 do_sys_open fs/open.c:1423 [inline] __do_sys_openat fs/open.c:1439 [inline] __se_sys_openat fs/open.c:1434 [inline] __x64_sys_openat+0x12d/0x210 fs/open.c:1434 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f other info that might help us debug this: Chain exists of: sb_writers#6 --> param_lock --> &ovl_i_mutex_dir_key[depth] Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&ovl_i_mutex_dir_key[depth]); lock(param_lock); lock(&ovl_i_mutex_dir_key[depth]); rlock(sb_writers#6); *** DEADLOCK *** locks held by syz-executor469/6041: 2, last CPU#2: #0: ffff88802a68c460 (sb_writers#13){.+.+}-{0:0}, at: lookup_open+0x150/0x1990 fs/namei.c:4451 #1: ffff88805802a7a8 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: inode_lock include/linux/fs.h:1024 [inline] #1: ffff88805802a7a8 (&ovl_i_mutex_dir_key[depth]){++++}-{4:4}, at: lookup_open+0xb13/0x1990 fs/namei.c:4458 stack backtrace: CPU: 2 UID: 0 PID: 6041 Comm: syz-executor469 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120 print_circular_bug.cold+0x178/0x1be kernel/locking/lockdep.c:2087 check_noncircular+0x146/0x160 kernel/locking/lockdep.c:2219 check_prev_add+0xeb/0xe60 kernel/locking/lockdep.c:3209 check_prevs_add kernel/locking/lockdep.c:3328 [inline] validate_chain kernel/locking/lockdep.c:3952 [inline] __lock_acquire+0x1528/0x1f40 kernel/locking/lockdep.c:5288 lock_acquire kernel/locking/lockdep.c:5942 [inline] lock_acquire+0x1d1/0x380 kernel/locking/lockdep.c:5899 percpu_down_read_internal include/linux/percpu-rwsem.h:53 [inline] percpu_down_read_freezable include/linux/percpu-rwsem.h:83 [inline] __sb_start_write include/linux/fs/super.h:19 [inline] sb_start_write include/linux/fs/super.h:125 [inline] mnt_want_write+0x6f/0x420 fs/namespace.c:494 ovl_create_object+0x130/0x3b0 fs/overlayfs/dir.c:705 lookup_open+0x1255/0x1990 fs/namei.c:4567 open_last_lookups fs/namei.c:4767 [inline] path_openat+0xa2c/0x2440 fs/namei.c:4997 do_file_open+0x20e/0x430 fs/namei.c:5029 do_sys_openat2+0x10f/0x1e0 fs/open.c:1417 do_sys_open fs/open.c:1423 [inline] __do_sys_openat fs/open.c:1439 [inline] __se_sys_openat fs/open.c:1434 [inline] __x64_sys_openat+0x12d/0x210 fs/open.c:1434 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fadca23e437 Code: 48 89 fa 4c 89 df e8 98 1d 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff RSP: 002b:00007fff380044d0 EFLAGS: 00000202 ORIG_RAX: 0000000000000101 RAX: ffffffffffffffda RBX: 000055555dddf400 RCX: 00007fadca23e437 RDX: 0000000000000042 RSI: 00007fadca277192 RDI: ffffffffffffff9c RBP: 00007fadca2770fe R08: 0000000000000000 R09: 0000000000000000 R10: 00000000000001a4 R11: 0000000000000202 R12: 000055555dde1770 R13: 0000000000000026 R14: 00007fff380045a0 R15: 0000000000000002 </TASK> --- If you want syzbot to run the reproducer, reply with: #syz test: git://repo/address.git branch-or-commit-hash If you attach or paste a git patch, syzbot will apply it before testing. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-09 15:19 [syzbot] [fs?] possible deadlock in ovl_create_object (2) syzbot 2026-09-12 13:12 ` syzbot @ 2026-09-16 19:48 ` Chris Roy 2026-09-16 21:37 ` Chris Roy 2026-09-20 18:51 ` [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write Chris Roy 2 siblings, 1 reply; 25+ messages in thread From: Chris Roy @ 2026-09-16 19:48 UTC (permalink / raw) To: syzbot Cc: dakr, driver-core, gregkh, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs On Thu, 17 Sept 2026 at 01:10, syzbot <syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com> wrote: > > Hello, > > syzbot found the following issue on: > > HEAD commit: 654ae5d73c05 Merge tag 'drm-fixes-2026-09-05' of https://g.. > git tree: upstream > console output: https://syzkaller.appspot.com/x/log.txt?x=11860cf9580000 > kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f > dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 > > Unfortunately, I don't have any reproducer for this issue yet. I am investigating this report and working on reproducing the lockdep cycle and identifying the root cause. I will follow up with findings and a proposed fix shortly. Regards, - Chris "But how could you live and have no story to tell?" ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-16 19:48 ` Chris Roy @ 2026-09-16 21:37 ` Chris Roy 2026-09-16 21:52 ` syzbot 0 siblings, 1 reply; 25+ messages in thread From: Chris Roy @ 2026-09-16 21:37 UTC (permalink / raw) To: syzbot Cc: dakr, driver-core, gregkh, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs [-- Attachment #1: Type: text/plain, Size: 1907 bytes --] On Wed, 9 Sep 2026 08:19:24 -0700, syzbot wrote: > syzbot found the following issue on: > ... > possible deadlock in ovl_create_object Follow-up to my earlier note: I reproduced this with the C reproducer. The cycle is not an overlayfs bug by itself. block2mtd_setup() opens the named block device (VFS path walk) while still under param_lock and the kernfs write path. When that write arrives via splice, a pipe mutex is held as well. That nests under already (the other way) ordered locks with overlay sb_writers / ovl_i_mutex. The attached patch drops param_lock and defers the open to a workqueue (still synchronous via wait_for_completion), so the VFS walk does not run under that stack. Local testing with the syzbot C repro: lockdep warning before the patch, clean after. #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master Please consider the patch for linux-mtd. On Thu, 17 Sept 2026 at 01:18, Chris Roy <iam@thechris.in> wrote: > > On Thu, 17 Sept 2026 at 01:10, syzbot > <syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com> wrote: > > > > Hello, > > > > syzbot found the following issue on: > > > > HEAD commit: 654ae5d73c05 Merge tag 'drm-fixes-2026-09-05' of https://g.. > > git tree: upstream > > console output: https://syzkaller.appspot.com/x/log.txt?x=11860cf9580000 > > kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f > > dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > > compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 > > > > Unfortunately, I don't have any reproducer for this issue yet. > > I am investigating this report and working on reproducing the lockdep > cycle and identifying the root cause. I will follow up with findings > and a proposed fix shortly. > > Regards, > - Chris > > "But how could you live and have no story to tell?" [-- Attachment #2: 0001-mtd-block2mtd-defer-device-open-out-of-param-sysfs-w.patch --] [-- Type: text/x-diff, Size: 6155 bytes --] From c39535066f53d998c716488273e86761bb8e2ade Mon Sep 17 00:00:00 2001 From: Chris Roy <iam@thechris.in> Date: Wed, 16 Sep 2026 21:09:49 +0000 Subject: [PATCH] mtd: block2mtd: defer device open out of param/sysfs write block2mtd_setup() is called from the module-parameter write path while param_lock is held, and from inside kernfs_fop_write_iter (which holds the kernfs inode mutex). When that write arrives via splice, a pipe mutex is held as well. The setup path then opens the named block device with bdev_file_open_by_path(), which walks the VFS. That nests inode / overlay directory locks and sb_writers under the locks above and creates a lockdep cycle, for example: sb_writers -> pipe -> kernfs/param -> ovl_i_mutex -> sb_writers syzbot reproduces it by splicing into an overlay file, splicing an overlay path into /sys/module/block2mtd/parameters/block2mtd, then creating a file on the overlay. Drop param_lock and run the open on a workqueue so VFS locking is not nested under the parameter/sysfs/pipe stack. Keep the call synchronous with wait_for_completion(). Protect the device list and the early-boot paramline buffer with a local mutex that is never held across a path lookup. Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 Signed-off-by: Chris Roy <iam@thechris.in> --- drivers/mtd/devices/block2mtd.c | 103 +++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 03e80b2c4..4ab4c31a2 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/mtd/mtd.h> #include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/completion.h> #include <linux/mount.h> #include <linux/slab.h> #include <linux/major.h> @@ -45,6 +47,7 @@ struct block2mtd_dev { /* Static info about the MTD, used in cleanup_module */ static LIST_HEAD(blkmtd_device_list); +static DEFINE_MUTEX(block2mtd_mutex); static struct page *page_read(struct address_space *mapping, pgoff_t index) @@ -329,7 +332,9 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size, goto err_destroy_mutex; } + mutex_lock(&block2mtd_mutex); list_add(&dev->list, &blkmtd_device_list); + mutex_unlock(&block2mtd_mutex); pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", dev->mtd.index, label ? label : dev->mtd.name + strlen("block2mtd: "), @@ -462,30 +467,77 @@ static int block2mtd_setup2(const char *val) } -static int block2mtd_setup(const char *val, const struct kernel_param *kp) + +struct block2mtd_setup_work { + struct work_struct work; + char *val; + struct completion done; + int ret; +}; + +static void block2mtd_setup_workfn(struct work_struct *work) { -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ + struct block2mtd_setup_work *w = + container_of(work, struct block2mtd_setup_work, work); + + w->ret = block2mtd_setup2(w->val); + complete(&w->done); +} + +/* + * Run device setup outside the module-parameter / kernfs write path. + * Those paths hold param_lock and the kernfs inode mutex (and, when the + * write arrives via splice, a pipe mutex). Opening a block device does + * VFS lookups and must not nest under that stack. + */ +static int block2mtd_setup_defer(const char *val) +{ + struct block2mtd_setup_work w = { + .ret = 0, + }; + + w.val = kstrdup(val, GFP_KERNEL); + if (!w.val) + return -ENOMEM; + + init_completion(&w.done); + INIT_WORK(&w.work, block2mtd_setup_workfn); + schedule_work(&w.work); + wait_for_completion(&w.done); + kfree(w.val); + return w.ret; +} - if (block2mtd_init_called) - return block2mtd_setup2(val); +static int block2mtd_setup(const char *val, const struct kernel_param *kp) +{ + int ret = 0; - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ + if (!try_module_get(kp->mod)) + return -ENODEV; - strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + /* + * Drop param_lock before scheduling. The actual open runs on a + * workqueue so it is also outside kernfs_fop_write_iter's inode + * mutex (and any pipe lock from splice). + */ + kernel_param_unlock(kp->mod); - return 0; +#ifdef MODULE + ret = block2mtd_setup_defer(val); +#else + if (block2mtd_init_called) { + ret = block2mtd_setup_defer(val); + } else { + mutex_lock(&block2mtd_mutex); + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + mutex_unlock(&block2mtd_mutex); + } #endif + + kernel_param_lock(kp->mod); + module_put(kp->mod); + + return ret; } @@ -497,9 +549,18 @@ static int __init block2mtd_init(void) int ret = 0; #ifndef MODULE - if (strlen(block2mtd_paramline)) - ret = block2mtd_setup2(block2mtd_paramline); + mutex_lock(&block2mtd_mutex); + if (strlen(block2mtd_paramline)) { + char buf[sizeof(block2mtd_paramline)]; + + strscpy(buf, block2mtd_paramline, sizeof(buf)); + mutex_unlock(&block2mtd_mutex); + /* init context: no kernfs/param locks held */ + ret = block2mtd_setup2(buf); + mutex_lock(&block2mtd_mutex); + } block2mtd_init_called = 1; + mutex_unlock(&block2mtd_mutex); #endif return ret; @@ -510,6 +571,7 @@ static void block2mtd_exit(void) { struct list_head *pos, *next; + mutex_lock(&block2mtd_mutex); /* Remove the MTD devices */ list_for_each_safe(pos, next, &blkmtd_device_list) { struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); @@ -522,6 +584,7 @@ static void block2mtd_exit(void) list_del(&dev->list); block2mtd_free_device(dev); } + mutex_unlock(&block2mtd_mutex); } late_initcall(block2mtd_init); -- 2.43.0 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-16 21:37 ` Chris Roy @ 2026-09-16 21:52 ` syzbot 2026-09-17 6:44 ` Chris Roy 0 siblings, 1 reply; 25+ messages in thread From: syzbot @ 2026-09-16 21:52 UTC (permalink / raw) To: dakr, driver-core, gregkh, iam, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs Hello, syzbot has tested the proposed patch but the reproducer is still triggering an issue: WARNING: ODEBUG bug in lookup_object_or_alloc ODEBUG: object ffffc90007cdf850 is on stack ffffc90007cd8000, but NOT annotated. ------------[ cut here ]------------ 1 WARNING: lib/debugobjects.c:672 at debug_object_is_on_stack lib/debugobjects.c:672 [inline], CPU#0: syz-executor162/6029 WARNING: lib/debugobjects.c:672 at lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705, CPU#0: syz-executor162/6029 Modules linked in: CPU: 0 UID: 0 PID: 6029 Comm: syz-executor162 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:debug_object_is_on_stack lib/debugobjects.c:672 [inline] RIP: 0010:lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705 Code: c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 83 c5 01 89 2d a0 1f 7d 1a 4c 89 e6 48 c7 c7 c0 39 62 8c e8 21 ae eb ff 90 <0f> 0b 90 e9 82 31 fe 03 83 c5 01 89 2d 7f 1f 7d 1a 49 39 c4 73 da RSP: 0018:ffffc90007cdf6c0 EFLAGS: 00010082 RAX: 0000000000000050 RBX: ffff88802cb1d738 RCX: 0000000000000000 RDX: 0000000000000050 RSI: ffffffff81ea1339 RDI: fffff52000f9bec9 RBP: 0000000000000001 R08: 0000000000000007 R09: 0000000000000000 R10: 8000000000000001 R11: 0000000000000001 R12: ffffc90007cdf850 R13: ffff888034204b00 R14: 0000000000000000 R15: 0000000000000000 FS: 00005555811b5400(0000) GS:ffff8880d5b57000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00005555811b8778 CR3: 000000002bbd8000 CR4: 0000000000352ef0 Call Trace: <TASK> lookup_object_or_alloc lib/debugobjects.c:682 [inline] __debug_object_init+0x2a9/0x3d0 lib/debugobjects.c:798 __init_work+0x51/0x60 kernel/workqueue.c:697 block2mtd_setup_defer+0xd7/0x1d0 drivers/mtd/devices/block2mtd.c:504 block2mtd_setup+0x9c/0x1e0 drivers/mtd/devices/block2mtd.c:529 param_attr_store+0x199/0x300 kernel/params.c:591 module_attr_store+0x58/0x80 kernel/params.c:906 sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 do_splice_from fs/splice.c:936 [inline] do_splice+0x109c/0x1fa0 fs/splice.c:1349 __do_splice+0x33b/0x370 fs/splice.c:1431 __do_sys_splice fs/splice.c:1634 [inline] __se_sys_splice fs/splice.c:1616 [inline] __x64_sys_splice+0x187/0x250 fs/splice.c:1616 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fa1c31b3437 Code: 48 89 fa 4c 89 df e8 98 1d 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff RSP: 002b:00007ffce5a2ac20 EFLAGS: 00000202 ORIG_RAX: 0000000000000113 RAX: ffffffffffffffda RBX: 00005555811b5400 RCX: 00007fa1c31b3437 RDX: 0000000000000005 RSI: 0000000000000000 RDI: 0000000000000003 RBP: 00007fa1c31ec0fe R08: 0000000000000026 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000202 R12: 00005555811b7770 R13: 0000000000000026 R14: 00007ffce5a2aca0 R15: 0000000000000002 </TASK> Tested on: commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=143de115580000 kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 patch: https://syzkaller.appspot.com/x/patch.diff?x=17ade115580000 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-16 21:52 ` syzbot @ 2026-09-17 6:44 ` Chris Roy 2026-09-17 6:59 ` syzbot 2026-09-17 7:33 ` Greg KH 0 siblings, 2 replies; 25+ messages in thread From: Chris Roy @ 2026-09-17 6:44 UTC (permalink / raw) To: syzbot Cc: dakr, driver-core, gregkh, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs [-- Attachment #1: Type: text/plain, Size: 4750 bytes --] On Wed, 9 Sep 2026 08:19:24 -0700, syzbot wrote: > syzbot found the following issue on: > ... > possible deadlock in ovl_create_object Follow-up / v2. v1 deferred the open with schedule_work() and an on-stack work_struct. That cleared the lockdep cycle, but syzbot reported an ODEBUG warning under CONFIG_DEBUG_OBJECTS_WORK. v2 uses a dedicated ordered workqueue and heap-allocated work, keeps a module reference across the deferred open, flushes the queue before exit, and serializes setup on the worker under a local mutex. Local testing with the C reproducer (LOCKDEP + DEBUG_OBJECTS_WORK): unpatched hits the circular locking warning; v2 is clean. #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master Please consider the patch for linux-mtd. On Thu, 17 Sept 2026 at 03:22, syzbot <syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com> wrote: > > Hello, > > syzbot has tested the proposed patch but the reproducer is still triggering an issue: > WARNING: ODEBUG bug in lookup_object_or_alloc > > ODEBUG: object ffffc90007cdf850 is on stack ffffc90007cd8000, but NOT annotated. > ------------[ cut here ]------------ > 1 > WARNING: lib/debugobjects.c:672 at debug_object_is_on_stack lib/debugobjects.c:672 [inline], CPU#0: syz-executor162/6029 > WARNING: lib/debugobjects.c:672 at lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705, CPU#0: syz-executor162/6029 > Modules linked in: > CPU: 0 UID: 0 PID: 6029 Comm: syz-executor162 Not tainted syzkaller #0 PREEMPT(full) > Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 > RIP: 0010:debug_object_is_on_stack lib/debugobjects.c:672 [inline] > RIP: 0010:lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705 > Code: c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 83 c5 01 89 2d a0 1f 7d 1a 4c 89 e6 48 c7 c7 c0 39 62 8c e8 21 ae eb ff 90 <0f> 0b 90 e9 82 31 fe 03 83 c5 01 89 2d 7f 1f 7d 1a 49 39 c4 73 da > RSP: 0018:ffffc90007cdf6c0 EFLAGS: 00010082 > RAX: 0000000000000050 RBX: ffff88802cb1d738 RCX: 0000000000000000 > RDX: 0000000000000050 RSI: ffffffff81ea1339 RDI: fffff52000f9bec9 > RBP: 0000000000000001 R08: 0000000000000007 R09: 0000000000000000 > R10: 8000000000000001 R11: 0000000000000001 R12: ffffc90007cdf850 > R13: ffff888034204b00 R14: 0000000000000000 R15: 0000000000000000 > FS: 00005555811b5400(0000) GS:ffff8880d5b57000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > CR2: 00005555811b8778 CR3: 000000002bbd8000 CR4: 0000000000352ef0 > Call Trace: > <TASK> > lookup_object_or_alloc lib/debugobjects.c:682 [inline] > __debug_object_init+0x2a9/0x3d0 lib/debugobjects.c:798 > __init_work+0x51/0x60 kernel/workqueue.c:697 > block2mtd_setup_defer+0xd7/0x1d0 drivers/mtd/devices/block2mtd.c:504 > block2mtd_setup+0x9c/0x1e0 drivers/mtd/devices/block2mtd.c:529 > param_attr_store+0x199/0x300 kernel/params.c:591 > module_attr_store+0x58/0x80 kernel/params.c:906 > sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 > kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 > iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 > do_splice_from fs/splice.c:936 [inline] > do_splice+0x109c/0x1fa0 fs/splice.c:1349 > __do_splice+0x33b/0x370 fs/splice.c:1431 > __do_sys_splice fs/splice.c:1634 [inline] > __se_sys_splice fs/splice.c:1616 [inline] > __x64_sys_splice+0x187/0x250 fs/splice.c:1616 > do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] > do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > RIP: 0033:0x7fa1c31b3437 > Code: 48 89 fa 4c 89 df e8 98 1d 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff > RSP: 002b:00007ffce5a2ac20 EFLAGS: 00000202 ORIG_RAX: 0000000000000113 > RAX: ffffffffffffffda RBX: 00005555811b5400 RCX: 00007fa1c31b3437 > RDX: 0000000000000005 RSI: 0000000000000000 RDI: 0000000000000003 > RBP: 00007fa1c31ec0fe R08: 0000000000000026 R09: 0000000000000000 > R10: 0000000000000000 R11: 0000000000000202 R12: 00005555811b7770 > R13: 0000000000000026 R14: 00007ffce5a2aca0 R15: 0000000000000002 > </TASK> > > > Tested on: > > commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. > git tree: upstream > console output: https://syzkaller.appspot.com/x/log.txt?x=143de115580000 > kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f > dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 > patch: https://syzkaller.appspot.com/x/patch.diff?x=17ade115580000 > [-- Attachment #2: 0001-mtd-block2mtd-defer-device-open-out-of-param-sysfs-w.patch --] [-- Type: text/x-diff, Size: 6392 bytes --] From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Chris Roy <iam@thechris.in> Date: Thu, 17 Sep 2026 00:00:00 +0000 Subject: [PATCH v2] mtd: block2mtd: defer device open out of param/sysfs write block2mtd_setup() opens the named block device (VFS path walk) while still under param_lock and kernfs_fop_write_iter. When that write arrives via splice, a pipe mutex is held as well. That nests under locks already ordered the other way with overlay sb_writers / ovl_i_mutex and triggers lockdep, for example: sb_writers -> pipe -> kernfs/param -> ovl_i_mutex -> sb_writers Drop param_lock and run setup on a dedicated ordered workqueue so the open is not nested under that stack. Keep the call synchronous with wait_for_completion(). Changes since v1: - allocate work on the heap (v1 tripped DEBUG_OBJECTS_WORK) - use a dedicated ordered workqueue instead of system_wq - hold a module reference across the deferred open - flush and destroy the workqueue before exit teardown - serialize setup2 on the worker under block2mtd_mutex - keep early-boot paramline updates under that mutex Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 Signed-off-by: Chris Roy <iam@thechris.in> --- drivers/mtd/devices/block2mtd.c | 121 ++++++++++++++++++++---- 1 file changed, 103 insertions(+), 18 deletions(-) --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/mtd/mtd.h> #include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/completion.h> #include <linux/mount.h> #include <linux/slab.h> #include <linux/major.h> @@ -45,6 +47,13 @@ /* Static info about the MTD, used in cleanup_module */ static LIST_HEAD(blkmtd_device_list); +/* + * Serializes setup/teardown (including list updates). Never held by a + * task that also holds param_lock / kernfs / pipe locks across a VFS open: + * deferred setup runs on block2mtd_wq instead. + */ +static DEFINE_MUTEX(block2mtd_mutex); +static struct workqueue_struct *block2mtd_wq; static struct page *page_read(struct address_space *mapping, pgoff_t index) @@ -461,31 +470,101 @@ return 0; } +struct block2mtd_setup_work { + struct work_struct work; + struct completion done; + char *val; + int ret; +}; + +static void block2mtd_setup_workfn(struct work_struct *work) +{ + struct block2mtd_setup_work *w = + container_of(work, struct block2mtd_setup_work, work); + + mutex_lock(&block2mtd_mutex); + w->ret = block2mtd_setup2(w->val); + mutex_unlock(&block2mtd_mutex); + complete(&w->done); +} + +/* + * Run device setup on block2mtd_wq so the VFS open is not nested under + * param_lock, the kernfs write inode mutex, or a splice pipe lock. + * Work is heap-allocated (not on-stack) for CONFIG_DEBUG_OBJECTS_WORK. + * Caller must hold a module reference until this returns. + */ +static int block2mtd_setup_defer(const char *val) +{ + struct block2mtd_setup_work *w; + int ret; + + if (!block2mtd_wq) + return -ENODEV; + + w = kzalloc(sizeof(*w), GFP_KERNEL); + if (!w) + return -ENOMEM; + + w->val = kstrdup(val, GFP_KERNEL); + if (!w->val) { + kfree(w); + return -ENOMEM; + } + + init_completion(&w->done); + INIT_WORK(&w->work, block2mtd_setup_workfn); + queue_work(block2mtd_wq, &w->work); + wait_for_completion(&w->done); + + ret = w->ret; + kfree(w->val); + kfree(w); + return ret; +} static int block2mtd_setup(const char *val, const struct kernel_param *kp) { -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ - - if (block2mtd_init_called) - return block2mtd_setup2(val); - - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ + int ret = 0; - strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + if (!try_module_get(kp->mod)) + return -ENODEV; - return 0; + /* + * Leave param_lock before any path that may open a block device. + * Sysfs/splice locks are still held here, so after init we must + * bounce to block2mtd_wq rather than calling setup2 in-task. + */ + kernel_param_unlock(kp->mod); + +#ifndef MODULE + mutex_lock(&block2mtd_mutex); + if (!block2mtd_init_called) { + /* Early boot: cannot resolve block devices yet. */ + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + mutex_unlock(&block2mtd_mutex); + kernel_param_lock(kp->mod); + module_put(kp->mod); + return 0; + } + mutex_unlock(&block2mtd_mutex); #endif + + if (block2mtd_wq) { + ret = block2mtd_setup_defer(val); + } else { + /* + * Module parameter applied before module_init (insmod + * args): no sysfs/splice nesting on this path. + */ + mutex_lock(&block2mtd_mutex); + ret = block2mtd_setup2(val); + mutex_unlock(&block2mtd_mutex); + } + + kernel_param_lock(kp->mod); + module_put(kp->mod); + return ret; } @@ -496,10 +575,20 @@ { int ret = 0; + block2mtd_wq = alloc_ordered_workqueue("block2mtd", 0); + if (!block2mtd_wq) + return -ENOMEM; + #ifndef MODULE + mutex_lock(&block2mtd_mutex); if (strlen(block2mtd_paramline)) ret = block2mtd_setup2(block2mtd_paramline); + /* + * Publish after early paramline is consumed so a concurrent + * sysfs write cannot race the buffer vs init_called. + */ block2mtd_init_called = 1; + mutex_unlock(&block2mtd_mutex); #endif return ret; @@ -510,9 +599,16 @@ { struct list_head *pos, *next; - /* Remove the MTD devices */ + if (block2mtd_wq) { + flush_workqueue(block2mtd_wq); + destroy_workqueue(block2mtd_wq); + block2mtd_wq = NULL; + } + + mutex_lock(&block2mtd_mutex); list_for_each_safe(pos, next, &blkmtd_device_list) { struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); + block2mtd_sync(&dev->mtd); mtd_device_unregister(&dev->mtd); mutex_destroy(&dev->write_mutex); @@ -522,6 +618,7 @@ list_del(&dev->list); block2mtd_free_device(dev); } + mutex_unlock(&block2mtd_mutex); } late_initcall(block2mtd_init); ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 6:44 ` Chris Roy @ 2026-09-17 6:59 ` syzbot 2026-09-17 7:33 ` Greg KH 1 sibling, 0 replies; 25+ messages in thread From: syzbot @ 2026-09-17 6:59 UTC (permalink / raw) To: dakr, driver-core, gregkh, iam, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs Hello, syzbot has tested the proposed patch and the reproducer did not trigger any issue: Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested on: commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=13824915580000 kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 patch: https://syzkaller.appspot.com/x/patch.diff?x=1493b925580000 Note: testing is done by a robot and is best-effort only. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 6:44 ` Chris Roy 2026-09-17 6:59 ` syzbot @ 2026-09-17 7:33 ` Greg KH 2026-09-17 7:58 ` Chris Roy 1 sibling, 1 reply; 25+ messages in thread From: Greg KH @ 2026-09-17 7:33 UTC (permalink / raw) To: Chris Roy Cc: syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs On Thu, Sep 17, 2026 at 12:14:05PM +0530, Chris Roy wrote: > On Wed, 9 Sep 2026 08:19:24 -0700, syzbot wrote: > > syzbot found the following issue on: > > ... > > possible deadlock in ovl_create_object > > Follow-up / v2. > > v1 deferred the open with schedule_work() and an on-stack work_struct. > That cleared the lockdep cycle, but syzbot reported an ODEBUG warning > under CONFIG_DEBUG_OBJECTS_WORK. > > v2 uses a dedicated ordered workqueue and heap-allocated work, keeps a > module reference across the deferred open, flushes the queue before > exit, and serializes setup on the worker under a local mutex. > > Local testing with the C reproducer (LOCKDEP + DEBUG_OBJECTS_WORK): > unpatched hits the circular locking warning; v2 is clean. > > #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git > master > > Please consider the patch for linux-mtd. > > On Thu, 17 Sept 2026 at 03:22, syzbot > <syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com> wrote: > > > > Hello, > > > > syzbot has tested the proposed patch but the reproducer is still triggering an issue: > > WARNING: ODEBUG bug in lookup_object_or_alloc > > > > ODEBUG: object ffffc90007cdf850 is on stack ffffc90007cd8000, but NOT annotated. > > ------------[ cut here ]------------ > > 1 > > WARNING: lib/debugobjects.c:672 at debug_object_is_on_stack lib/debugobjects.c:672 [inline], CPU#0: syz-executor162/6029 > > WARNING: lib/debugobjects.c:672 at lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705, CPU#0: syz-executor162/6029 > > Modules linked in: > > CPU: 0 UID: 0 PID: 6029 Comm: syz-executor162 Not tainted syzkaller #0 PREEMPT(full) > > Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 > > RIP: 0010:debug_object_is_on_stack lib/debugobjects.c:672 [inline] > > RIP: 0010:lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705 > > Code: c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 83 c5 01 89 2d a0 1f 7d 1a 4c 89 e6 48 c7 c7 c0 39 62 8c e8 21 ae eb ff 90 <0f> 0b 90 e9 82 31 fe 03 83 c5 01 89 2d 7f 1f 7d 1a 49 39 c4 73 da > > RSP: 0018:ffffc90007cdf6c0 EFLAGS: 00010082 > > RAX: 0000000000000050 RBX: ffff88802cb1d738 RCX: 0000000000000000 > > RDX: 0000000000000050 RSI: ffffffff81ea1339 RDI: fffff52000f9bec9 > > RBP: 0000000000000001 R08: 0000000000000007 R09: 0000000000000000 > > R10: 8000000000000001 R11: 0000000000000001 R12: ffffc90007cdf850 > > R13: ffff888034204b00 R14: 0000000000000000 R15: 0000000000000000 > > FS: 00005555811b5400(0000) GS:ffff8880d5b57000(0000) knlGS:0000000000000000 > > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > > CR2: 00005555811b8778 CR3: 000000002bbd8000 CR4: 0000000000352ef0 > > Call Trace: > > <TASK> > > lookup_object_or_alloc lib/debugobjects.c:682 [inline] > > __debug_object_init+0x2a9/0x3d0 lib/debugobjects.c:798 > > __init_work+0x51/0x60 kernel/workqueue.c:697 > > block2mtd_setup_defer+0xd7/0x1d0 drivers/mtd/devices/block2mtd.c:504 > > block2mtd_setup+0x9c/0x1e0 drivers/mtd/devices/block2mtd.c:529 > > param_attr_store+0x199/0x300 kernel/params.c:591 > > module_attr_store+0x58/0x80 kernel/params.c:906 > > sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 > > kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 > > iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 > > do_splice_from fs/splice.c:936 [inline] > > do_splice+0x109c/0x1fa0 fs/splice.c:1349 > > __do_splice+0x33b/0x370 fs/splice.c:1431 > > __do_sys_splice fs/splice.c:1634 [inline] > > __se_sys_splice fs/splice.c:1616 [inline] > > __x64_sys_splice+0x187/0x250 fs/splice.c:1616 > > do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] > > do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 > > entry_SYSCALL_64_after_hwframe+0x77/0x7f > > RIP: 0033:0x7fa1c31b3437 > > Code: 48 89 fa 4c 89 df e8 98 1d 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff > > RSP: 002b:00007ffce5a2ac20 EFLAGS: 00000202 ORIG_RAX: 0000000000000113 > > RAX: ffffffffffffffda RBX: 00005555811b5400 RCX: 00007fa1c31b3437 > > RDX: 0000000000000005 RSI: 0000000000000000 RDI: 0000000000000003 > > RBP: 00007fa1c31ec0fe R08: 0000000000000026 R09: 0000000000000000 > > R10: 0000000000000000 R11: 0000000000000202 R12: 00005555811b7770 > > R13: 0000000000000026 R14: 00007ffce5a2aca0 R15: 0000000000000002 > > </TASK> > > > > > > Tested on: > > > > commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. > > git tree: upstream > > console output: https://syzkaller.appspot.com/x/log.txt?x=143de115580000 > > kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f > > dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > > compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 > > patch: https://syzkaller.appspot.com/x/patch.diff?x=17ade115580000 > > > From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 > From: Chris Roy <iam@thechris.in> > Date: Thu, 17 Sep 2026 00:00:00 +0000 > Subject: [PATCH v2] mtd: block2mtd: defer device open out of param/sysfs write > > block2mtd_setup() opens the named block device (VFS path walk) while > still under param_lock and kernfs_fop_write_iter. When that write > arrives via splice, a pipe mutex is held as well. That nests under > locks already ordered the other way with overlay sb_writers / > ovl_i_mutex and triggers lockdep, for example: > > sb_writers -> pipe -> kernfs/param -> ovl_i_mutex -> sb_writers > > Drop param_lock and run setup on a dedicated ordered workqueue so the > open is not nested under that stack. Keep the call synchronous with > wait_for_completion(). > > Changes since v1: > - allocate work on the heap (v1 tripped DEBUG_OBJECTS_WORK) > - use a dedicated ordered workqueue instead of system_wq > - hold a module reference across the deferred open > - flush and destroy the workqueue before exit teardown > - serialize setup2 on the worker under block2mtd_mutex > - keep early-boot paramline updates under that mutex > > Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > Signed-off-by: Chris Roy <iam@thechris.in> > --- > drivers/mtd/devices/block2mtd.c | 121 ++++++++++++++++++++---- > 1 file changed, 103 insertions(+), 18 deletions(-) Did you forget the Assisted-by: tag? > > --- a/drivers/mtd/devices/block2mtd.c > +++ b/drivers/mtd/devices/block2mtd.c > @@ -27,6 +27,8 @@ > #include <linux/init.h> > #include <linux/mtd/mtd.h> > #include <linux/mutex.h> > +#include <linux/workqueue.h> > +#include <linux/completion.h> > #include <linux/mount.h> > #include <linux/slab.h> > #include <linux/major.h> > @@ -45,6 +47,13 @@ > > /* Static info about the MTD, used in cleanup_module */ > static LIST_HEAD(blkmtd_device_list); > +/* > + * Serializes setup/teardown (including list updates). Never held by a > + * task that also holds param_lock / kernfs / pipe locks across a VFS open: > + * deferred setup runs on block2mtd_wq instead. Make the comments make sense please. That's the problem of using a LLM :( thanks, greg k-h ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 7:33 ` Greg KH @ 2026-09-17 7:58 ` Chris Roy 2026-09-17 8:13 ` syzbot 2026-09-17 18:15 ` Jörn Engel 0 siblings, 2 replies; 25+ messages in thread From: Chris Roy @ 2026-09-17 7:58 UTC (permalink / raw) To: Greg KH Cc: syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, richard, vigneshr, joern [-- Attachment #1: Type: text/plain, Size: 8056 bytes --] On Thu, Sep 17, 2026 at 13:05:00 +0530, Greg KH wrote: > Did you forget the Assisted-by: tag? > > Make the comments make sense please. That's the problem of using a LLM :( Fair. v3 adds Assisted-by and rewrites those comments. Same approach as v2 otherwise. syzbot tested v2 cleanly on this bug. #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master Please consider for linux-mtd. On Thu, 17 Sept 2026 at 13:05, Greg KH <gregkh@linuxfoundation.org> wrote: > > On Thu, Sep 17, 2026 at 12:14:05PM +0530, Chris Roy wrote: > > On Wed, 9 Sep 2026 08:19:24 -0700, syzbot wrote: > > > syzbot found the following issue on: > > > ... > > > possible deadlock in ovl_create_object > > > > Follow-up / v2. > > > > v1 deferred the open with schedule_work() and an on-stack work_struct. > > That cleared the lockdep cycle, but syzbot reported an ODEBUG warning > > under CONFIG_DEBUG_OBJECTS_WORK. > > > > v2 uses a dedicated ordered workqueue and heap-allocated work, keeps a > > module reference across the deferred open, flushes the queue before > > exit, and serializes setup on the worker under a local mutex. > > > > Local testing with the C reproducer (LOCKDEP + DEBUG_OBJECTS_WORK): > > unpatched hits the circular locking warning; v2 is clean. > > > > #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git > > master > > > > Please consider the patch for linux-mtd. > > > > On Thu, 17 Sept 2026 at 03:22, syzbot > > <syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com> wrote: > > > > > > Hello, > > > > > > syzbot has tested the proposed patch but the reproducer is still triggering an issue: > > > WARNING: ODEBUG bug in lookup_object_or_alloc > > > > > > ODEBUG: object ffffc90007cdf850 is on stack ffffc90007cd8000, but NOT annotated. > > > ------------[ cut here ]------------ > > > 1 > > > WARNING: lib/debugobjects.c:672 at debug_object_is_on_stack lib/debugobjects.c:672 [inline], CPU#0: syz-executor162/6029 > > > WARNING: lib/debugobjects.c:672 at lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705, CPU#0: syz-executor162/6029 > > > Modules linked in: > > > CPU: 0 UID: 0 PID: 6029 Comm: syz-executor162 Not tainted syzkaller #0 PREEMPT(full) > > > Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 > > > RIP: 0010:debug_object_is_on_stack lib/debugobjects.c:672 [inline] > > > RIP: 0010:lookup_object_or_alloc.part.0.cold+0x19/0x40 lib/debugobjects.c:705 > > > Code: c4 60 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 83 c5 01 89 2d a0 1f 7d 1a 4c 89 e6 48 c7 c7 c0 39 62 8c e8 21 ae eb ff 90 <0f> 0b 90 e9 82 31 fe 03 83 c5 01 89 2d 7f 1f 7d 1a 49 39 c4 73 da > > > RSP: 0018:ffffc90007cdf6c0 EFLAGS: 00010082 > > > RAX: 0000000000000050 RBX: ffff88802cb1d738 RCX: 0000000000000000 > > > RDX: 0000000000000050 RSI: ffffffff81ea1339 RDI: fffff52000f9bec9 > > > RBP: 0000000000000001 R08: 0000000000000007 R09: 0000000000000000 > > > R10: 8000000000000001 R11: 0000000000000001 R12: ffffc90007cdf850 > > > R13: ffff888034204b00 R14: 0000000000000000 R15: 0000000000000000 > > > FS: 00005555811b5400(0000) GS:ffff8880d5b57000(0000) knlGS:0000000000000000 > > > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > > > CR2: 00005555811b8778 CR3: 000000002bbd8000 CR4: 0000000000352ef0 > > > Call Trace: > > > <TASK> > > > lookup_object_or_alloc lib/debugobjects.c:682 [inline] > > > __debug_object_init+0x2a9/0x3d0 lib/debugobjects.c:798 > > > __init_work+0x51/0x60 kernel/workqueue.c:697 > > > block2mtd_setup_defer+0xd7/0x1d0 drivers/mtd/devices/block2mtd.c:504 > > > block2mtd_setup+0x9c/0x1e0 drivers/mtd/devices/block2mtd.c:529 > > > param_attr_store+0x199/0x300 kernel/params.c:591 > > > module_attr_store+0x58/0x80 kernel/params.c:906 > > > sysfs_kf_write+0xf2/0x150 fs/sysfs/file.c:145 > > > kernfs_fop_write_iter+0x3e0/0x5f0 fs/kernfs/file.c:345 > > > iter_file_splice_write+0x830/0x10b0 fs/splice.c:736 > > > do_splice_from fs/splice.c:936 [inline] > > > do_splice+0x109c/0x1fa0 fs/splice.c:1349 > > > __do_splice+0x33b/0x370 fs/splice.c:1431 > > > __do_sys_splice fs/splice.c:1634 [inline] > > > __se_sys_splice fs/splice.c:1616 [inline] > > > __x64_sys_splice+0x187/0x250 fs/splice.c:1616 > > > do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] > > > do_syscall_64+0x123/0x790 arch/x86/entry/syscall_64.c:84 > > > entry_SYSCALL_64_after_hwframe+0x77/0x7f > > > RIP: 0033:0x7fa1c31b3437 > > > Code: 48 89 fa 4c 89 df e8 98 1d 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff > > > RSP: 002b:00007ffce5a2ac20 EFLAGS: 00000202 ORIG_RAX: 0000000000000113 > > > RAX: ffffffffffffffda RBX: 00005555811b5400 RCX: 00007fa1c31b3437 > > > RDX: 0000000000000005 RSI: 0000000000000000 RDI: 0000000000000003 > > > RBP: 00007fa1c31ec0fe R08: 0000000000000026 R09: 0000000000000000 > > > R10: 0000000000000000 R11: 0000000000000202 R12: 00005555811b7770 > > > R13: 0000000000000026 R14: 00007ffce5a2aca0 R15: 0000000000000002 > > > </TASK> > > > > > > > > > Tested on: > > > > > > commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. > > > git tree: upstream > > > console output: https://syzkaller.appspot.com/x/log.txt?x=143de115580000 > > > kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f > > > dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > > > compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 > > > patch: https://syzkaller.appspot.com/x/patch.diff?x=17ade115580000 > > > > > > From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 > > From: Chris Roy <iam@thechris.in> > > Date: Thu, 17 Sep 2026 00:00:00 +0000 > > Subject: [PATCH v2] mtd: block2mtd: defer device open out of param/sysfs write > > > > block2mtd_setup() opens the named block device (VFS path walk) while > > still under param_lock and kernfs_fop_write_iter. When that write > > arrives via splice, a pipe mutex is held as well. That nests under > > locks already ordered the other way with overlay sb_writers / > > ovl_i_mutex and triggers lockdep, for example: > > > > sb_writers -> pipe -> kernfs/param -> ovl_i_mutex -> sb_writers > > > > Drop param_lock and run setup on a dedicated ordered workqueue so the > > open is not nested under that stack. Keep the call synchronous with > > wait_for_completion(). > > > > Changes since v1: > > - allocate work on the heap (v1 tripped DEBUG_OBJECTS_WORK) > > - use a dedicated ordered workqueue instead of system_wq > > - hold a module reference across the deferred open > > - flush and destroy the workqueue before exit teardown > > - serialize setup2 on the worker under block2mtd_mutex > > - keep early-boot paramline updates under that mutex > > > > Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com > > Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > > Signed-off-by: Chris Roy <iam@thechris.in> > > --- > > drivers/mtd/devices/block2mtd.c | 121 ++++++++++++++++++++---- > > 1 file changed, 103 insertions(+), 18 deletions(-) > > Did you forget the Assisted-by: tag? > > > > > --- a/drivers/mtd/devices/block2mtd.c > > +++ b/drivers/mtd/devices/block2mtd.c > > @@ -27,6 +27,8 @@ > > #include <linux/init.h> > > #include <linux/mtd/mtd.h> > > #include <linux/mutex.h> > > +#include <linux/workqueue.h> > > +#include <linux/completion.h> > > #include <linux/mount.h> > > #include <linux/slab.h> > > #include <linux/major.h> > > @@ -45,6 +47,13 @@ > > > > /* Static info about the MTD, used in cleanup_module */ > > static LIST_HEAD(blkmtd_device_list); > > +/* > > + * Serializes setup/teardown (including list updates). Never held by a > > + * task that also holds param_lock / kernfs / pipe locks across a VFS open: > > + * deferred setup runs on block2mtd_wq instead. > > Make the comments make sense please. That's the problem of using a LLM :( > > thanks, > > greg k-h [-- Attachment #2: 0001-mtd-block2mtd-defer-device-open-out-of-param-sysfs-w.patch --] [-- Type: text/x-diff, Size: 5697 bytes --] From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Chris Roy <iam@thechris.in> Date: Thu, 17 Sep 2026 00:00:00 +0000 Subject: [PATCH v3] mtd: block2mtd: defer device open out of param/sysfs write block2mtd_setup() opens the named block device while still under param_lock, and on the sysfs write path under kernfs (and possibly a splice pipe lock). That nests VFS locking the wrong way relative to overlayfs and trips lockdep. Drop param_lock and run setup on a dedicated ordered workqueue. Keep the call synchronous with wait_for_completion(). Allocate the work on the heap so DEBUG_OBJECTS_WORK stays quiet. Changes since v2: - rewrite the new comments to match the rest of the file Changes since v1: - heap-allocated work (v1 tripped DEBUG_OBJECTS_WORK) - dedicated ordered workqueue instead of system_wq - module reference across the deferred open - flush/destroy the workqueue before exit teardown - serialize setup2 on the worker under block2mtd_mutex - early-boot paramline updates under that mutex Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 Assisted-by: Mistral, Qwen Signed-off-by: Chris Roy <iam@thechris.in> --- drivers/mtd/devices/block2mtd.c | 118 ++++++++++++++++++++----- 1 file changed, 98 insertions(+), 20 deletions(-) --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/mtd/mtd.h> #include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/completion.h> #include <linux/mount.h> #include <linux/slab.h> #include <linux/major.h> @@ -45,6 +47,9 @@ /* Static info about the MTD, used in cleanup_module */ static LIST_HEAD(blkmtd_device_list); +/* Protects blkmtd_device_list and early-boot paramline updates */ +static DEFINE_MUTEX(block2mtd_mutex); +static struct workqueue_struct *block2mtd_wq; static struct page *page_read(struct address_space *mapping, pgoff_t index) @@ -461,31 +466,89 @@ return 0; } +struct block2mtd_setup_work { + struct work_struct work; + struct completion done; + char *val; + int ret; +}; + +static void block2mtd_setup_workfn(struct work_struct *work) +{ + struct block2mtd_setup_work *w = + container_of(work, struct block2mtd_setup_work, work); + + mutex_lock(&block2mtd_mutex); + w->ret = block2mtd_setup2(w->val); + mutex_unlock(&block2mtd_mutex); + complete(&w->done); +} + +/* Queue setup2 on block2mtd_wq; caller holds a module ref until return */ +static int block2mtd_setup_defer(const char *val) +{ + struct block2mtd_setup_work *w; + int ret; + + if (!block2mtd_wq) + return -ENODEV; + + w = kzalloc(sizeof(*w), GFP_KERNEL); + if (!w) + return -ENOMEM; + + w->val = kstrdup(val, GFP_KERNEL); + if (!w->val) { + kfree(w); + return -ENOMEM; + } + + init_completion(&w->done); + INIT_WORK(&w->work, block2mtd_setup_workfn); + queue_work(block2mtd_wq, &w->work); + wait_for_completion(&w->done); + + ret = w->ret; + kfree(w->val); + kfree(w); + return ret; +} static int block2mtd_setup(const char *val, const struct kernel_param *kp) { -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ - - if (block2mtd_init_called) - return block2mtd_setup2(val); - - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ + int ret = 0; - strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + if (!try_module_get(kp->mod)) + return -ENODEV; - return 0; + /* Do not open a block device under param_lock */ + kernel_param_unlock(kp->mod); + +#ifndef MODULE + mutex_lock(&block2mtd_mutex); + if (!block2mtd_init_called) { + /* Early boot: cannot resolve block devices yet. */ + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + mutex_unlock(&block2mtd_mutex); + kernel_param_lock(kp->mod); + module_put(kp->mod); + return 0; + } + mutex_unlock(&block2mtd_mutex); #endif + + if (block2mtd_wq) { + ret = block2mtd_setup_defer(val); + } else { + /* Pre-init (e.g. insmod args): safe to run setup2 here */ + mutex_lock(&block2mtd_mutex); + ret = block2mtd_setup2(val); + mutex_unlock(&block2mtd_mutex); + } + + kernel_param_lock(kp->mod); + module_put(kp->mod); + return ret; } @@ -496,10 +559,17 @@ { int ret = 0; + block2mtd_wq = alloc_ordered_workqueue("block2mtd", 0); + if (!block2mtd_wq) + return -ENOMEM; + #ifndef MODULE + mutex_lock(&block2mtd_mutex); if (strlen(block2mtd_paramline)) ret = block2mtd_setup2(block2mtd_paramline); + /* Avoid racing sysfs with the early paramline */ block2mtd_init_called = 1; + mutex_unlock(&block2mtd_mutex); #endif return ret; @@ -510,9 +580,16 @@ { struct list_head *pos, *next; - /* Remove the MTD devices */ + if (block2mtd_wq) { + flush_workqueue(block2mtd_wq); + destroy_workqueue(block2mtd_wq); + block2mtd_wq = NULL; + } + + mutex_lock(&block2mtd_mutex); list_for_each_safe(pos, next, &blkmtd_device_list) { struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); + block2mtd_sync(&dev->mtd); mtd_device_unregister(&dev->mtd); mutex_destroy(&dev->write_mutex); @@ -522,6 +599,7 @@ list_del(&dev->list); block2mtd_free_device(dev); } + mutex_unlock(&block2mtd_mutex); } late_initcall(block2mtd_init); ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 7:58 ` Chris Roy @ 2026-09-17 8:13 ` syzbot 2026-09-17 18:15 ` Jörn Engel 1 sibling, 0 replies; 25+ messages in thread From: syzbot @ 2026-09-17 8:13 UTC (permalink / raw) To: dakr, driver-core, gregkh, iam, joern, linux-fsdevel, linux-kernel, linux-mtd, miquel.raynal, rafael, richard, syzkaller-bugs, vigneshr Hello, syzbot has tested the proposed patch and the reproducer did not trigger any issue: Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested on: commit: 238650ef Merge tag 'powerpc-7.3-4' of git://git.kernel.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=165358c9580000 kernel config: https://syzkaller.appspot.com/x/.config?x=8c5c3949d762a91f dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 patch: https://syzkaller.appspot.com/x/patch.diff?x=117a3bf9580000 Note: testing is done by a robot and is best-effort only. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 7:58 ` Chris Roy 2026-09-17 8:13 ` syzbot @ 2026-09-17 18:15 ` Jörn Engel 2026-09-19 7:42 ` AW: " Richard Weinberger 1 sibling, 1 reply; 25+ messages in thread From: Jörn Engel @ 2026-09-17 18:15 UTC (permalink / raw) To: Chris Roy Cc: Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, richard, vigneshr, joern On Thu, Sep 17, 2026 at 01:28:22PM +0530, Chris Roy wrote: > > drivers/mtd/devices/block2mtd.c | 118 ++++++++++++++++++++----- > 1 file changed, 98 insertions(+), 20 deletions(-) [...] > /* Static info about the MTD, used in cleanup_module */ > static LIST_HEAD(blkmtd_device_list); > +/* Protects blkmtd_device_list and early-boot paramline updates */ > +static DEFINE_MUTEX(block2mtd_mutex); > +static struct workqueue_struct *block2mtd_wq; This is just awful taste. You are inside a file called "block2mtd". The prefix to the mutex an workqueue add absolutely nothing. Calling them just plain "mutex" and "wq" would have been a better choice. Good names should tell the human reader something. What is the mutex protecting? What is the purpose of the workqueue? Pick a name that gives us some information like that, please! You seem to have used AI to write this code, so the bad name choice was presumably also done by AI. But you are still associating your own good name with the code. You should try not to harm your good name by letting things like this slide through unchallenged. Jörn -- Do not stop an army on its way home. -- Sun Tzu ^ permalink raw reply [flat|nested] 25+ messages in thread
* AW: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-17 18:15 ` Jörn Engel @ 2026-09-19 7:42 ` Richard Weinberger 2026-09-19 8:52 ` Chris Roy 2026-09-19 14:21 ` AW: " Jörn Engel 0 siblings, 2 replies; 25+ messages in thread From: Richard Weinberger @ 2026-09-19 7:42 UTC (permalink / raw) To: Jörn Engel, Chris Roy Cc: Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, joern Am Thu, Sep 17, 2026, 20:16 schrieb Jörn Engel <joern@barelysecure.org>: > On Thu, Sep 17, 2026 at 01:28:22PM +0530, Chris Roy wrote: > > > > drivers/mtd/devices/block2mtd.c | 118 ++++++++++++++++++++----- > > 1 file changed, 98 insertions(+), 20 deletions(-) > [...] > > /* Static info about the MTD, used in cleanup_module */ > > static LIST_HEAD(blkmtd_device_list); > > +/* Protects blkmtd_device_list and early-boot paramline updates */ > > +static DEFINE_MUTEX(block2mtd_mutex); > > +static struct workqueue_struct *block2mtd_wq; > > This is just awful taste. You are inside a file called "block2mtd". > The prefix to the mutex an workqueue add absolutely nothing. Calling > them just plain "mutex" and "wq" would have been a better choice. > > Good names should tell the human reader something. What is the mutex > protecting? What is the purpose of the workqueue? Pick a name that > gives us some information like that, please! > > > You seem to have used AI to write this code, so the bad name choice was > presumably also done by AI. But you are still associating your own good > name with the code. You should try not to harm your good name by > letting things like this slide through unchallenged. While we're here, maybe it's time to add a decent configfs interface to this driver instead of configuring through module parameters. That way also multiple instances are possible. Thanks, //richard ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 7:42 ` AW: " Richard Weinberger @ 2026-09-19 8:52 ` Chris Roy 2026-09-19 9:07 ` syzbot 2026-09-19 14:45 ` Jörn Engel 2026-09-19 14:21 ` AW: " Jörn Engel 1 sibling, 2 replies; 25+ messages in thread From: Chris Roy @ 2026-09-19 8:52 UTC (permalink / raw) To: Richard Weinberger Cc: Jörn Engel, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, joern [-- Attachment #1: Type: text/plain, Size: 754 bytes --] On Sat, Sep 19, 2026, Jörn Engel wrote: > This is just awful taste. You are inside a file called "block2mtd". > The prefix to the mutex an workqueue add absolutely nothing. > [...] > Pick a name that gives us some information like that, please! Agreed. v4 renames to list_mutex and setup_wq. Additionally, I fixed tag formatting and removed a redundant if-guard. On Sat, Sep 19, 2026, Richard Weinberger wrote: > While we're here, maybe it's time to add a decent configfs interface > to this driver instead of configuring through module parameters. I will look at a configfs interface as a follow up once this lockdep fix lands. #syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master Regards, Chris [-- Attachment #2: 0001-mtd-block2mtd-defer-device-open-out-of-param-sysfs-w.patch --] [-- Type: text/x-patch, Size: 6081 bytes --] From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Chris Roy <iam@thechris.in> Date: Sat, 19 Sep 2026 00:00:00 +0000 Subject: [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write block2mtd_setup() opens the named block device while still under param_lock, and on the sysfs write path under kernfs (and possibly a splice pipe lock). That nests VFS locking the wrong way relative to overlayfs and trips lockdep. Drop param_lock and run setup on a dedicated ordered workqueue. Keep the call synchronous with wait_for_completion(). Allocate the work on the heap so DEBUG_OBJECTS_WORK stays quiet. Changes since v3: - rename list_mutex / setup_wq to say what they are for - tidy new comments - fix Assisted-by tag format (checkpatch: AGENT_NAME:MODEL_VERSION) - drop redundant setup_wq check in block2mtd_setup_defer() (the sole caller already gates on it) Changes since v2: - rewrite the new comments to match the rest of the file - add Assisted-by Changes since v1: - heap-allocated work (v1 tripped DEBUG_OBJECTS_WORK) - dedicated ordered workqueue instead of system_wq - module reference across the deferred open - flush/destroy the workqueue before exit teardown - serialize setup2 on the worker under list_mutex - early-boot paramline updates under that mutex Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Chris Roy <iam@thechris.in> --- drivers/mtd/devices/block2mtd.c | 116 ++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 03e80b2..a540089 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/mtd/mtd.h> #include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/completion.h> #include <linux/mount.h> #include <linux/slab.h> #include <linux/major.h> @@ -45,6 +47,9 @@ struct block2mtd_dev { /* Static info about the MTD, used in cleanup_module */ static LIST_HEAD(blkmtd_device_list); +/* Protects blkmtd_device_list and early-boot paramline updates */ +static DEFINE_MUTEX(list_mutex); +static struct workqueue_struct *setup_wq; static struct page *page_read(struct address_space *mapping, pgoff_t index) @@ -461,31 +466,85 @@ static int block2mtd_setup2(const char *val) return 0; } +struct block2mtd_setup_work { + struct work_struct work; + struct completion done; + char *val; + int ret; +}; + +static void block2mtd_setup_workfn(struct work_struct *work) +{ + struct block2mtd_setup_work *w = + container_of(work, struct block2mtd_setup_work, work); + + mutex_lock(&list_mutex); + w->ret = block2mtd_setup2(w->val); + mutex_unlock(&list_mutex); + complete(&w->done); +} + +/* Runs block2mtd_setup2() on setup_wq, blocking until it completes */ +static int block2mtd_setup_defer(const char *val) +{ + struct block2mtd_setup_work *w; + int ret; + + w = kzalloc(sizeof(*w), GFP_KERNEL); + if (!w) + return -ENOMEM; + + w->val = kstrdup(val, GFP_KERNEL); + if (!w->val) { + kfree(w); + return -ENOMEM; + } + + init_completion(&w->done); + INIT_WORK(&w->work, block2mtd_setup_workfn); + queue_work(setup_wq, &w->work); + wait_for_completion(&w->done); + + ret = w->ret; + kfree(w->val); + kfree(w); + return ret; +} static int block2mtd_setup(const char *val, const struct kernel_param *kp) { -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ - - if (block2mtd_init_called) - return block2mtd_setup2(val); - - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ + int ret = 0; - strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + if (!try_module_get(kp->mod)) + return -ENODEV; - return 0; + kernel_param_unlock(kp->mod); + +#ifndef MODULE + mutex_lock(&list_mutex); + if (!block2mtd_init_called) { + /* Cannot resolve block devices this early */ + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + mutex_unlock(&list_mutex); + kernel_param_lock(kp->mod); + module_put(kp->mod); + return 0; + } + mutex_unlock(&list_mutex); #endif + + if (setup_wq) { + ret = block2mtd_setup_defer(val); + } else { + /* Not yet deferred to setup_wq; safe to call setup2 directly */ + mutex_lock(&list_mutex); + ret = block2mtd_setup2(val); + mutex_unlock(&list_mutex); + } + + kernel_param_lock(kp->mod); + module_put(kp->mod); + return ret; } @@ -496,10 +555,17 @@ static int __init block2mtd_init(void) { int ret = 0; + setup_wq = alloc_ordered_workqueue("block2mtd", 0); + if (!setup_wq) + return -ENOMEM; + #ifndef MODULE + mutex_lock(&list_mutex); if (strlen(block2mtd_paramline)) ret = block2mtd_setup2(block2mtd_paramline); + /* Avoid racing sysfs with the early paramline */ block2mtd_init_called = 1; + mutex_unlock(&list_mutex); #endif return ret; @@ -510,9 +576,16 @@ static void block2mtd_exit(void) { struct list_head *pos, *next; - /* Remove the MTD devices */ + if (setup_wq) { + flush_workqueue(setup_wq); + destroy_workqueue(setup_wq); + setup_wq = NULL; + } + + mutex_lock(&list_mutex); list_for_each_safe(pos, next, &blkmtd_device_list) { struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); + block2mtd_sync(&dev->mtd); mtd_device_unregister(&dev->mtd); mutex_destroy(&dev->write_mutex); @@ -522,6 +595,7 @@ static void block2mtd_exit(void) list_del(&dev->list); block2mtd_free_device(dev); } + mutex_unlock(&list_mutex); } late_initcall(block2mtd_init); -- 2.43.0 ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 8:52 ` Chris Roy @ 2026-09-19 9:07 ` syzbot 2026-09-19 14:45 ` Jörn Engel 1 sibling, 0 replies; 25+ messages in thread From: syzbot @ 2026-09-19 9:07 UTC (permalink / raw) To: dakr, driver-core, gregkh, iam, joern, joern, linux-fsdevel, linux-kernel, linux-mtd, miquel.raynal, rafael, richard, syzkaller-bugs, vigneshr Hello, syzbot has tested the proposed patch and the reproducer did not trigger any issue: Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Tested on: commit: 40288c92 Merge tag 'drm-fixes-2026-09-19' of https://g.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=169d2ff9580000 kernel config: https://syzkaller.appspot.com/x/.config?x=84649d3ff8d550cb dashboard link: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44 patch: https://syzkaller.appspot.com/x/patch.diff?x=11b52ff9580000 Note: testing is done by a robot and is best-effort only. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 8:52 ` Chris Roy 2026-09-19 9:07 ` syzbot @ 2026-09-19 14:45 ` Jörn Engel 2026-09-19 15:28 ` Chris Roy 1 sibling, 1 reply; 25+ messages in thread From: Jörn Engel @ 2026-09-19 14:45 UTC (permalink / raw) To: Chris Roy Cc: Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das On Sat, Sep 19, 2026 at 02:22:15PM +0530, Chris Roy wrote: > > +struct block2mtd_setup_work { > + struct work_struct work; > + struct completion done; > + char *val; > + int ret; > +}; Finding good names is probably a fetish of mine, so "val" is mildly disturbing to me. It's not an objectively bad name, just something where I'd spend another five minutes trying to come up with something better. > +/* Runs block2mtd_setup2() on setup_wq, blocking until it completes */ > +static int block2mtd_setup_defer(const char *val) > +{ > + struct block2mtd_setup_work *w; > + int ret; > + > + w = kzalloc(sizeof(*w), GFP_KERNEL); > + if (!w) > + return -ENOMEM; Is this check necessary? I'm in the camp of "malloc should never return NULL". That condition is so rare that it is effectively impossible to trust callers with error handling. So the right approach is to crash (or kernel panic here) instead of returning an error. Looking into sources I see this: static inline void *kzalloc(size_t s, gfp_t gfp) > { > void *p = kmalloc(s, gfp); > > memset(p, 0, s); > return p; > } We have at least one example of explicitly not checking the return value. But we have other prominent examples of checking as well. Looks like the kernel is still undecided whether checks are necessary or not. > - return block2mtd_setup2(val); ... > - return block2mtd_setup2(val); ... > + ret = block2mtd_setup2(val); ... > ret = block2mtd_setup2(block2mtd_paramline); That's quite a few calls to the same function. If setup gets that complicated, that's a strong indication that we're doing things wrong. Typically we get into such a mess one well-intentioned change at a time. Find a bug, fix it by adding another caller, repeat. It isn't obvious how we could improve things. Sometimes it's lack of infrastructure and the entire complicated setup-dance should be moved to common code. Driver can then call a single function to deal with everything. But if there's only a single driver using such infrastructure, maybe the driver is doing things wrong and should copy whatever other drivers are doing. The problem shouldn't be unique to a single driver, so we should find the best solution and then use it everywhere. I don't know the correct answer here. If you feel motivated to dig deeper, please do! If not, I'd rather leave the mess in place than come up with a half-hearted attempt of a solution. Jörn -- You cannot suppose that Moliere ever troubled himself to be original in the matter of ideas. You cannot suppose that the stories he tells in his plays have never been told before. They were culled, as you very well know. -- Andre-Louis Moreau in Scarabouche ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 14:45 ` Jörn Engel @ 2026-09-19 15:28 ` Chris Roy 2026-09-19 15:38 ` Jörn Engel 0 siblings, 1 reply; 25+ messages in thread From: Chris Roy @ 2026-09-19 15:28 UTC (permalink / raw) To: Jörn Engel Cc: Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das On Sat, Sep 19, 2026, Jörn Engel wrote: > Finding good names is probably a fetish of mine, so "val" is mildly > disturbing to me. [...] I have a similar pet peeve in my domain. I kept "val" since it mirrors block2mtd_setup2()'s own "val" parameter (the raw <dev>[,[<erasesize>][,<label>]]), so I kept it for consistency with the existing call chain. I had considered "spec" but probably it would have been similarly unimaginative. > Is this check necessary? [...] Looks like the kernel is still > undecided whether checks are necessary or not. I will keep it. kzalloc()/kstrdup() under plain GFP_KERNEL can still return NULL under real memory pressure (no __GFP_NOFAIL here), and dropping it would be inconsistent with the kstrdup() check two lines below. > That's quite a few calls to the same function. [...] If you feel > motivated to dig deeper, please do! If not, I'd rather leave the > mess in place than come up with a half-hearted attempt of a > solution. True. It is accretion. I'd rather not bolt a redesign onto this fix. However, I can look at setup2()'s callers as a separate effort. Regards, - Chris "But how could you live and have no story to tell?" On Sat, 19 Sept 2026 at 20:16, Jörn Engel <joern@barelysecure.org> wrote: > > On Sat, Sep 19, 2026 at 02:22:15PM +0530, Chris Roy wrote: > > > > +struct block2mtd_setup_work { > > + struct work_struct work; > > + struct completion done; > > + char *val; > > + int ret; > > +}; > > Finding good names is probably a fetish of mine, so "val" is mildly > disturbing to me. It's not an objectively bad name, just something > where I'd spend another five minutes trying to come up with something > better. > > > +/* Runs block2mtd_setup2() on setup_wq, blocking until it completes */ > > +static int block2mtd_setup_defer(const char *val) > > +{ > > + struct block2mtd_setup_work *w; > > + int ret; > > + > > + w = kzalloc(sizeof(*w), GFP_KERNEL); > > + if (!w) > > + return -ENOMEM; > > Is this check necessary? I'm in the camp of "malloc should never return > NULL". That condition is so rare that it is effectively impossible to > trust callers with error handling. So the right approach is to crash > (or kernel panic here) instead of returning an error. > > Looking into sources I see this: > static inline void *kzalloc(size_t s, gfp_t gfp) > > { > > void *p = kmalloc(s, gfp); > > > > memset(p, 0, s); > > return p; > > } > > We have at least one example of explicitly not checking the return > value. But we have other prominent examples of checking as well. Looks > like the kernel is still undecided whether checks are necessary or not. > > > - return block2mtd_setup2(val); > ... > > - return block2mtd_setup2(val); > ... > > + ret = block2mtd_setup2(val); > ... > > ret = block2mtd_setup2(block2mtd_paramline); > > That's quite a few calls to the same function. If setup gets that > complicated, that's a strong indication that we're doing things wrong. > Typically we get into such a mess one well-intentioned change at a time. > Find a bug, fix it by adding another caller, repeat. > > It isn't obvious how we could improve things. Sometimes it's lack of > infrastructure and the entire complicated setup-dance should be moved to > common code. Driver can then call a single function to deal with > everything. > > But if there's only a single driver using such infrastructure, maybe the > driver is doing things wrong and should copy whatever other drivers are > doing. The problem shouldn't be unique to a single driver, so we should > find the best solution and then use it everywhere. > > I don't know the correct answer here. If you feel motivated to dig > deeper, please do! If not, I'd rather leave the mess in place than come > up with a half-hearted attempt of a solution. > > Jörn > > -- > You cannot suppose that Moliere ever troubled himself to be original in the > matter of ideas. You cannot suppose that the stories he tells in his plays > have never been told before. They were culled, as you very well know. > -- Andre-Louis Moreau in Scarabouche ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 15:28 ` Chris Roy @ 2026-09-19 15:38 ` Jörn Engel 2026-09-20 12:52 ` Miquel Raynal 0 siblings, 1 reply; 25+ messages in thread From: Jörn Engel @ 2026-09-19 15:38 UTC (permalink / raw) To: Chris Roy Cc: Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das On Sat, Sep 19, 2026 at 08:58:51PM +0530, Chris Roy wrote: > > I'd rather not bolt a redesign onto this fix. Good decision! > > Is this check necessary? [...] Looks like the kernel is still > > undecided whether checks are necessary or not. > > I will keep it. kzalloc()/kstrdup() under plain GFP_KERNEL can still > return NULL under real memory pressure (no __GFP_NOFAIL here), and > dropping it would be inconsistent with the kstrdup() check two lines > below. My foggy mind is slowly waking up. GFP_ATOMIC can return NULL. If you're trying to allocate memory from an interrupt handler or similar, you cannot afford to wait for memory reclaim to happen. Those calls definitely need a check and a reasonable plan what to do in case of failure. GFP_KERNEL should be able to block and wait, so there really is no excuse for kmalloc to return NULL or for the callers to need a check. But your decision of not pulling too many decisions into a single patch is still a good decision. Even if my logic is sound, removing checks from kmalloc callers should be a separate effort. Jörn -- I don't understand it. Nobody does. -- Richard P. Feynman ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 15:38 ` Jörn Engel @ 2026-09-20 12:52 ` Miquel Raynal 2026-09-20 16:19 ` Jörn Engel 0 siblings, 1 reply; 25+ messages in thread From: Miquel Raynal @ 2026-09-20 12:52 UTC (permalink / raw) To: Jörn Engel Cc: Chris Roy, Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, vigneshr, Adarsh Das Hi Jörn, >> > Is this check necessary? [...] Looks like the kernel is still >> > undecided whether checks are necessary or not. >> >> I will keep it. kzalloc()/kstrdup() under plain GFP_KERNEL can still >> return NULL under real memory pressure (no __GFP_NOFAIL here), and >> dropping it would be inconsistent with the kstrdup() check two lines >> below. > > My foggy mind is slowly waking up. GFP_ATOMIC can return NULL. If > you're trying to allocate memory from an interrupt handler or similar, > you cannot afford to wait for memory reclaim to happen. Those calls > definitely need a check and a reasonable plan what to do in case of > failure. > > GFP_KERNEL should be able to block and wait, so there really is no > excuse for kmalloc to return NULL or for the callers to need a check. > > But your decision of not pulling too many decisions into a single patch > is still a good decision. Even if my logic is sound, removing checks > from kmalloc callers should be a separate effort. Not saying this would be a bad move, it would be highly inconsistent with the current code base. Every single allocation in the kernel is checked. Such a change, without a documented and agreed upon method, would lead to dozens fuzzing AIs sending patches to add the "missing" check. Thanks, Miquèl ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-20 12:52 ` Miquel Raynal @ 2026-09-20 16:19 ` Jörn Engel 2026-09-20 18:34 ` Chris Roy 0 siblings, 1 reply; 25+ messages in thread From: Jörn Engel @ 2026-09-20 16:19 UTC (permalink / raw) To: Miquel Raynal Cc: Chris Roy, Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, vigneshr, Adarsh Das Hello Miquèl On Sun, Sep 20, 2026 at 02:52:18PM +0200, Miquel Raynal wrote: > > Not saying this would be a bad move, it would be highly inconsistent > with the current code base. Every single allocation in the kernel is > checked. Such a change, without a documented and agreed upon method, > would lead to dozens fuzzing AIs sending patches to add the "missing" > check. If your argument is that such a change would be inappropriate for the patch in question, I totally agree with you. I would disagree with an argument of "we should do the wrong thing for the sake of consistency". If indeed it is the wrong thing, we should stop doing it. Then we can regain consistency by not doing the wrong thing anywhere. In other words, consistency is irrelevant. The only question should be whether such a change is right or wrong. There is also the practical consideration that changing the kmalloc interface will lead to thousands of changes throughout the kernel and requires a large time commitment from someone. If nobody volunteers to be that someone, it might still be better to stick with the status quo for now. So making an entirely theoretical "if I were king for a day" kind of argument, I don't think GFP_KERNEL allocations should have to check for failure. Neither should userspace callers to malloc. An interface that frequently returns errors is pretty safe, as callers with broken error handling are quickly detected and fixes. An interface that almost never returns errors is dangerous, as broken error handling in callers becomes common and will eventually lead to bizarre hard-to-reproduce failures. One of my roles in my last job was to fix userspace malloc and one of my fixes was to ensure it would never return an allocation failure. If it returned, the caller received what it requested. If that wasn't possible, the process would crash. A crashing process isn't exactly desired, but it beats unpredictable behavior triggered by broken error handlers. And dealing with a single error path costs significantly less cognitive effort than dealing with thousands of error handlers everywhere in the code base. Anyway, since I am not volunteering to spend a significant chunk of my time, this is just the opinion of someone that doesn't matter. Feel free to reject it. Jörn -- Why do musicians compose symphonies and poets write poems? They do it because life wouldn't have any meaning for them if they didn't. That's why I draw cartoons. It's my life. -- Charles Shultz ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-20 16:19 ` Jörn Engel @ 2026-09-20 18:34 ` Chris Roy 0 siblings, 0 replies; 25+ messages in thread From: Chris Roy @ 2026-09-20 18:34 UTC (permalink / raw) To: Jörn Engel Cc: Miquel Raynal, Richard Weinberger, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, vigneshr, Adarsh Das #syz set subsystems: mtd Regards, - Chris "But how could you live and have no story to tell?" On Sun, 20 Sept 2026 at 21:50, Jörn Engel <joern@barelysecure.org> wrote: > > Hello Miquèl > > On Sun, Sep 20, 2026 at 02:52:18PM +0200, Miquel Raynal wrote: > > > > Not saying this would be a bad move, it would be highly inconsistent > > with the current code base. Every single allocation in the kernel is > > checked. Such a change, without a documented and agreed upon method, > > would lead to dozens fuzzing AIs sending patches to add the "missing" > > check. > > If your argument is that such a change would be inappropriate for the > patch in question, I totally agree with you. > > I would disagree with an argument of "we should do the wrong thing for > the sake of consistency". If indeed it is the wrong thing, we should > stop doing it. Then we can regain consistency by not doing the wrong > thing anywhere. In other words, consistency is irrelevant. The only > question should be whether such a change is right or wrong. > > There is also the practical consideration that changing the kmalloc > interface will lead to thousands of changes throughout the kernel and > requires a large time commitment from someone. If nobody volunteers to > be that someone, it might still be better to stick with the status quo > for now. > > > So making an entirely theoretical "if I were king for a day" kind of > argument, I don't think GFP_KERNEL allocations should have to check for > failure. Neither should userspace callers to malloc. An interface that > frequently returns errors is pretty safe, as callers with broken error > handling are quickly detected and fixes. An interface that almost never > returns errors is dangerous, as broken error handling in callers becomes > common and will eventually lead to bizarre hard-to-reproduce failures. > > One of my roles in my last job was to fix userspace malloc and one of my > fixes was to ensure it would never return an allocation failure. If it > returned, the caller received what it requested. If that wasn't > possible, the process would crash. A crashing process isn't exactly > desired, but it beats unpredictable behavior triggered by broken error > handlers. And dealing with a single error path costs significantly less > cognitive effort than dealing with thousands of error handlers > everywhere in the code base. > > Anyway, since I am not volunteering to spend a significant chunk of my > time, this is just the opinion of someone that doesn't matter. Feel > free to reject it. > > Jörn > > -- > Why do musicians compose symphonies and poets write poems? > They do it because life wouldn't have any meaning for them if they didn't. > That's why I draw cartoons. It's my life. > -- Charles Shultz ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: AW: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 7:42 ` AW: " Richard Weinberger 2026-09-19 8:52 ` Chris Roy @ 2026-09-19 14:21 ` Jörn Engel 2026-09-19 14:28 ` Richard Weinberger 1 sibling, 1 reply; 25+ messages in thread From: Jörn Engel @ 2026-09-19 14:21 UTC (permalink / raw) To: Richard Weinberger Cc: Chris Roy, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das I added Adarsh Das, who also attempted to fix this bug. On Sat, Sep 19, 2026 at 07:42:25AM +0000, Richard Weinberger wrote: > > While we're here, maybe it's time to add a decent configfs interface to > this driver instead of configuring through module parameters. > That way also multiple instances are possible. I honestly wonder whether this driver has any production users. It is somewhat useful for developers that want to simulate hardware they don't have. But beyond that? Anyway, I have two deeper review questions as well. One, afaics block2mtd predates overlayfs. If the bug requires the interaction of both, it is overlayfs that introduced the bug. So why do we fix it by modifying block2mtd? Is that really the appropriate way to fix it? Two, we fix the deadlock by adding a second thread (via workqueue). But to keep synchronous behavior we end up blocking until the second thread has finished. Does the blocking behavior recreate a circular dependency and therefore a deadlock? If not, why not? Jörn -- Prosperity makes friends, adversity tries them. -- Publilius Syrus ^ permalink raw reply [flat|nested] 25+ messages in thread
* AW: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 14:21 ` AW: " Jörn Engel @ 2026-09-19 14:28 ` Richard Weinberger 2026-09-19 14:44 ` Chris Roy 0 siblings, 1 reply; 25+ messages in thread From: Richard Weinberger @ 2026-09-19 14:28 UTC (permalink / raw) To: Jörn Engel Cc: Chris Roy, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das Am Sat, Sep 19, 2026, 16:22 schrieb Jörn Engel <joern@barelysecure.org>: > I added Adarsh Das, who also attempted to fix this bug. > > On Sat, Sep 19, 2026 at 07:42:25AM +0000, Richard Weinberger wrote: > > > > While we're here, maybe it's time to add a decent configfs interface to > > this driver instead of configuring through module parameters. > > That way also multiple instances are possible. > > I honestly wonder whether this driver has any production users. It is > somewhat useful for developers that want to simulate hardware they don't > have. But beyond that? IMHO testing is the only use case. I use it regularly. Thanks, //richard ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [syzbot] [fs?] possible deadlock in ovl_create_object (2) 2026-09-19 14:28 ` Richard Weinberger @ 2026-09-19 14:44 ` Chris Roy 0 siblings, 0 replies; 25+ messages in thread From: Chris Roy @ 2026-09-19 14:44 UTC (permalink / raw) To: Richard Weinberger Cc: Jörn Engel, Greg KH, syzbot, dakr, driver-core, linux-fsdevel, linux-kernel, rafael, syzkaller-bugs, linux-mtd, miquel.raynal, vigneshr, Adarsh Das On Sat, Sep 19, 2026, Richard Weinberger wrote: > While we're here, maybe it's time to add a decent configfs interface to > this driver instead of configuring through module parameters. > That way also multiple instances are possible. > > IMHO testing is the only use case. I use it regularly. I would love to look at this if you think it's worth the added complexity. A couple of design questions before I start on anything: - Does configfs coexist with the existing block2mtd= module param (for early-boot/cmdline compatibility), or replace it outright? - For multiple instances, would a configfs group per device (backing path, erase size, label) match what you had in mind? Can sketch an RFC-style doc once I have a sense of the above. Regards, Chris On Sat, 19 Sept 2026 at 19:58, Richard Weinberger <richard@nod.at> wrote: > > Am Sat, Sep 19, 2026, 16:22 schrieb Jörn Engel <joern@barelysecure.org>: > > I added Adarsh Das, who also attempted to fix this bug. > > > > On Sat, Sep 19, 2026 at 07:42:25AM +0000, Richard Weinberger wrote: > > > > > > While we're here, maybe it's time to add a decent configfs interface to > > > this driver instead of configuring through module parameters. > > > That way also multiple instances are possible. > > > > I honestly wonder whether this driver has any production users. It is > > somewhat useful for developers that want to simulate hardware they don't > > have. But beyond that? > > IMHO testing is the only use case. I use it regularly. > > Thanks, > //richard ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write 2026-09-09 15:19 [syzbot] [fs?] possible deadlock in ovl_create_object (2) syzbot 2026-09-12 13:12 ` syzbot 2026-09-16 19:48 ` Chris Roy @ 2026-09-20 18:51 ` Chris Roy 2026-09-20 19:03 ` sashiko-bot 2 siblings, 1 reply; 25+ messages in thread From: Chris Roy @ 2026-09-20 18:51 UTC (permalink / raw) To: miquel.raynal, richard, vigneshr Cc: linux-mtd, joern, gregkh, linux-kernel, syzbot+7cab6a19619f1b8efc00, syzkaller-bugs, Chris Roy block2mtd_setup() opens the named block device while still under param_lock, and on the sysfs write path under kernfs (and possibly a splice pipe lock). That nests VFS locking the wrong way relative to overlayfs and trips lockdep. Drop param_lock and run setup on a dedicated ordered workqueue. Keep the call synchronous with wait_for_completion(). Allocate the work on the heap so DEBUG_OBJECTS_WORK stays quiet. Reported-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 Tested-by: syzbot+7cab6a19619f1b8efc00@syzkaller.appspotmail.com Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Chris Roy <iam@thechris.in> --- v4: - rename list_mutex / setup_wq to say what they are for - tidy new comments - fix Assisted-by tag format (checkpatch: AGENT_NAME:MODEL_VERSION) - drop redundant setup_wq check in block2mtd_setup_defer() (the sole caller already gates on it) - claim Tested-by from syzbot (granted on v2, v3, and this content) v3: - rewrite the new comments to match the rest of the file - add Assisted-by v2: - heap-allocated work (v1 tripped DEBUG_OBJECTS_WORK) - dedicated ordered workqueue instead of system_wq - module reference across the deferred open - flush/destroy the workqueue before exit teardown - serialize setup2 on the worker under list_mutex - early-boot paramline updates under that mutex Not proposed for stable. block2mtd has no known production use (per Richard Weinberger, testing is the only real use case), so there is no backport trail worth chasing here. drivers/mtd/devices/block2mtd.c | 116 ++++++++++++++++++++++++++------ 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 03e80b2..a540089 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -27,6 +27,8 @@ #include <linux/init.h> #include <linux/mtd/mtd.h> #include <linux/mutex.h> +#include <linux/workqueue.h> +#include <linux/completion.h> #include <linux/mount.h> #include <linux/slab.h> #include <linux/major.h> @@ -45,6 +47,9 @@ struct block2mtd_dev { /* Static info about the MTD, used in cleanup_module */ static LIST_HEAD(blkmtd_device_list); +/* Protects blkmtd_device_list and early-boot paramline updates */ +static DEFINE_MUTEX(list_mutex); +static struct workqueue_struct *setup_wq; static struct page *page_read(struct address_space *mapping, pgoff_t index) @@ -461,31 +466,85 @@ static int block2mtd_setup2(const char *val) return 0; } +struct block2mtd_setup_work { + struct work_struct work; + struct completion done; + char *val; + int ret; +}; + +static void block2mtd_setup_workfn(struct work_struct *work) +{ + struct block2mtd_setup_work *w = + container_of(work, struct block2mtd_setup_work, work); + + mutex_lock(&list_mutex); + w->ret = block2mtd_setup2(w->val); + mutex_unlock(&list_mutex); + complete(&w->done); +} + +/* Runs block2mtd_setup2() on setup_wq, blocking until it completes */ +static int block2mtd_setup_defer(const char *val) +{ + struct block2mtd_setup_work *w; + int ret; + + w = kzalloc(sizeof(*w), GFP_KERNEL); + if (!w) + return -ENOMEM; + + w->val = kstrdup(val, GFP_KERNEL); + if (!w->val) { + kfree(w); + return -ENOMEM; + } + + init_completion(&w->done); + INIT_WORK(&w->work, block2mtd_setup_workfn); + queue_work(setup_wq, &w->work); + wait_for_completion(&w->done); + + ret = w->ret; + kfree(w->val); + kfree(w); + return ret; +} static int block2mtd_setup(const char *val, const struct kernel_param *kp) { -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ - - if (block2mtd_init_called) - return block2mtd_setup2(val); - - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ - - strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + int ret = 0; - return 0; + if (!try_module_get(kp->mod)) + return -ENODEV; + + kernel_param_unlock(kp->mod); + +#ifndef MODULE + mutex_lock(&list_mutex); + if (!block2mtd_init_called) { + /* Cannot resolve block devices this early */ + strscpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); + mutex_unlock(&list_mutex); + kernel_param_lock(kp->mod); + module_put(kp->mod); + return 0; + } + mutex_unlock(&list_mutex); #endif + + if (setup_wq) { + ret = block2mtd_setup_defer(val); + } else { + /* Not yet deferred to setup_wq; safe to call setup2 directly */ + mutex_lock(&list_mutex); + ret = block2mtd_setup2(val); + mutex_unlock(&list_mutex); + } + + kernel_param_lock(kp->mod); + module_put(kp->mod); + return ret; } @@ -496,10 +555,17 @@ static int __init block2mtd_init(void) { int ret = 0; + setup_wq = alloc_ordered_workqueue("block2mtd", 0); + if (!setup_wq) + return -ENOMEM; + #ifndef MODULE + mutex_lock(&list_mutex); if (strlen(block2mtd_paramline)) ret = block2mtd_setup2(block2mtd_paramline); + /* Avoid racing sysfs with the early paramline */ block2mtd_init_called = 1; + mutex_unlock(&list_mutex); #endif return ret; @@ -510,9 +576,16 @@ static void block2mtd_exit(void) { struct list_head *pos, *next; - /* Remove the MTD devices */ + if (setup_wq) { + flush_workqueue(setup_wq); + destroy_workqueue(setup_wq); + setup_wq = NULL; + } + + mutex_lock(&list_mutex); list_for_each_safe(pos, next, &blkmtd_device_list) { struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list); + block2mtd_sync(&dev->mtd); mtd_device_unregister(&dev->mtd); mutex_destroy(&dev->write_mutex); @@ -522,6 +595,7 @@ static void block2mtd_exit(void) list_del(&dev->list); block2mtd_free_device(dev); } + mutex_unlock(&list_mutex); } late_initcall(block2mtd_init); ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write 2026-09-20 18:51 ` [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write Chris Roy @ 2026-09-20 19:03 ` sashiko-bot 0 siblings, 0 replies; 25+ messages in thread From: sashiko-bot @ 2026-09-20 19:03 UTC (permalink / raw) To: miquel.raynal, richard, Chris Roy, vigneshr Cc: syzkaller-bugs, linux-mtd, joern, linux-kernel, gregkh, syzbot+7cab6a19619f1b8efc00 Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] mtd: block2mtd: use-after-free and resource leak on init failure - [High] mtd: block2mtd: sysfs lock inversion bypasses workqueue deferral -- commit c3f3ebd86ecc63dd07e6a22d8527eadaeb761633 Author: Chris Roy <iam@thechris.in> mtd: block2mtd: defer device open out of param/sysfs write This patch defers block2mtd_setup() device opening to a dedicated ordered workqueue to prevent lockdep-detected lock inversion between VFS and kernfs/overlayfs during sysfs writes. The setup work is executed via a dynamically allocated work item, preserving synchronous behavior with wait_for_completion(). Closes: https://syzkaller.appspot.com/bug?extid=7cab6a19619f1b8efc00 > diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c > index 349fa07be314c..30ac9325bdd2b 100644 > --- a/drivers/mtd/devices/block2mtd.c > +++ b/drivers/mtd/devices/block2mtd.c [ ... ] > @@ -461,31 +466,85 @@ static int block2mtd_setup2(const char *val) [ ... ] > static int block2mtd_setup(const char *val, const struct kernel_param *kp) > { [ ... ] > + if (setup_wq) { > + ret = block2mtd_setup_defer(val); > + } else { > + /* Not yet deferred to setup_wq; safe to call setup2 directly */ > + mutex_lock(&list_mutex); > + ret = block2mtd_setup2(val); > + mutex_unlock(&list_mutex); > + } [Severity: High] Does evaluating setup_wq here bypass the workqueue deferral and re-introduce the sysfs lock inversion? Since mod_sysfs_setup() exposes module parameters to sysfs before do_init_module() calls block2mtd_init(), setup_wq can be NULL during a concurrent sysfs write. This would cause the sysfs writer to execute block2mtd_setup2() inline under the sysfs kernfs lock. Additionally, since setup_wq is assigned in block2mtd_init() without memory barriers (such as smp_store_release() and smp_load_acquire()), concurrent sysfs writers might observe a stale NULL pointer even after initialization completes. > + > + kernel_param_lock(kp->mod); > + module_put(kp->mod); > + return ret; > } > > > @@ -496,10 +555,17 @@ static int __init block2mtd_init(void) > { > int ret = 0; > > + setup_wq = alloc_ordered_workqueue("block2mtd", 0); > + if (!setup_wq) > + return -ENOMEM; [Severity: High] Can returning -ENOMEM here lead to a use-after-free and resource leak? If parameters are provided during module load (e.g., insmod block2mtd.ko block2mtd=...), block2mtd_setup() is executed before block2mtd_init(). Because setup_wq is NULL at that time, it synchronously registers the MTD device in the block2mtd_setup() else branch shown above. If alloc_ordered_workqueue() subsequently fails here, it returns -ENOMEM and aborts the module load. The kernel frees the module memory without calling block2mtd_exit(), leaving the registered MTD device holding dangling function pointers to the unloaded module text. -- Sashiko AI review · https://sashiko.dev/#/patchset/20260920185132.1266699-1-iam@thechris.in?part=1 ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2026-09-20 19:03 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-09 15:19 [syzbot] [fs?] possible deadlock in ovl_create_object (2) syzbot 2026-09-12 13:12 ` syzbot 2026-09-16 19:48 ` Chris Roy 2026-09-16 21:37 ` Chris Roy 2026-09-16 21:52 ` syzbot 2026-09-17 6:44 ` Chris Roy 2026-09-17 6:59 ` syzbot 2026-09-17 7:33 ` Greg KH 2026-09-17 7:58 ` Chris Roy 2026-09-17 8:13 ` syzbot 2026-09-17 18:15 ` Jörn Engel 2026-09-19 7:42 ` AW: " Richard Weinberger 2026-09-19 8:52 ` Chris Roy 2026-09-19 9:07 ` syzbot 2026-09-19 14:45 ` Jörn Engel 2026-09-19 15:28 ` Chris Roy 2026-09-19 15:38 ` Jörn Engel 2026-09-20 12:52 ` Miquel Raynal 2026-09-20 16:19 ` Jörn Engel 2026-09-20 18:34 ` Chris Roy 2026-09-19 14:21 ` AW: " Jörn Engel 2026-09-19 14:28 ` Richard Weinberger 2026-09-19 14:44 ` Chris Roy 2026-09-20 18:51 ` [PATCH v4] mtd: block2mtd: defer device open out of param/sysfs write Chris Roy 2026-09-20 19:03 ` sashiko-bot
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®