[BUG REPORT] ntfs: possible circular locking dependency in ntfs_mft_writepages
From: yangguikun19
Date: Mon Jun 22 2026 - 02:24:39 EST
Hello,
syzkaller found a reproducible lockdep warning in the NTFS filesystem on a vanilla Linux 7.1.1 kernel. This is a possible circular locking dependency in ntfs_mft_writepages()/ntfs_write_mft_block() when writing back $MFT records from a crafted NTFS image.
I have not confirmed an exact public syzbot duplicate for this title/function. The closest known public family I found is a different classic-NTFS deadlock report in ntfs_read_folio, so I am reporting this as a separate issue.
Kernel:
Linux 7.1.1
target: linux/amd64
config highlights: CONFIG_NTFS_FS=y, CONFIG_NTFS3_FS=m, CONFIG_LOCKDEP=y, CONFIG_PROVE_LOCKING=y, KASAN enabled
Reproducer status:
syzkaller generated both syz and C reproducers.
An isolated same-kernel replay with syz-repro -count 1 confirmed the issue from the original execution log.
The isolated replay printed:
2026/06/22 05:13:52 reproducing crash 'possible deadlock in ntfs_mft_writepages': program crashed: possible deadlock in ntfs_mft_writepages
2026/06/22 05:13:52 reproducing crash 'possible deadlock in ntfs_mft_writepages': single: successfully extracted reproducer
2026/06/22 05:13:52 reproducing crash 'possible deadlock in ntfs_mft_writepages': found reproducer with 2 syscalls
High-level trigger:
syz_mount_image$ntfs(... crafted NTFS image ...)
setxattr$security_ima("./file0", ...)
Lockdep report excerpt:
wlan1: Creating new IBSS network, BSSID 50:50:50:50:50:50
======================================================
WARNING: possible circular locking dependency detected
7.1.1 #1 Tainted: G W
------------------------------------------------------
kworker/u9:5/4025 is trying to acquire lock:
ff11000023a05630 (&mft_ni_runlist_lock_key){++++}-{4:4}, at: ntfs_write_mft_block fs/ntfs/mft.c:2825 [inline]
ff11000023a05630 (&mft_ni_runlist_lock_key){++++}-{4:4}, at: ntfs_mft_writepages+0x1113/0x2410 fs/ntfs/mft.c:2955
but task is already holding lock:
ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_may_write_mft_record fs/ntfs/mft.c:931 [inline]
ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_write_mft_block fs/ntfs/mft.c:2788 [inline]
ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_mft_writepages+0x1c6d/0x2410 fs/ntfs/mft.c:2955
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&extent_inode_mrec_lock_key){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x178/0x1d20 kernel/locking/mutex.c:820
__ntfs_write_inode+0xc73/0x1530 fs/ntfs/inode.c:2813
write_inode fs/fs-writeback.c:1584 [inline]
__writeback_single_inode+0xcbf/0x1380 fs/fs-writeback.c:1827
writeback_sb_inodes+0x71c/0x1b60 fs/fs-writeback.c:2056
wb_writeback+0x404/0xbc0 fs/fs-writeback.c:2241
wb_do_writeback fs/fs-writeback.c:2388 [inline]
wb_workfn+0x158/0xbc0 fs/fs-writeback.c:2428
process_one_work+0x9dc/0x1c20 kernel/workqueue.c:3314
process_scheduled_works kernel/workqueue.c:3397 [inline]
worker_thread+0x693/0xea0 kernel/workqueue.c:3478
kthread+0x403/0x530 kernel/kthread.c:436
ret_from_fork+0xafe/0xda0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
-> #1 (&ni->extent_lock){+.+.}-{4:4}:
__mutex_lock_common kernel/locking/mutex.c:646 [inline]
__mutex_lock+0x178/0x1d20 kernel/locking/mutex.c:820
__ntfs_write_inode+0xa12/0x1530 fs/ntfs/inode.c:2781
write_inode fs/fs-writeback.c:1584 [inline]
__writeback_single_inode+0xcbf/0x1380 fs/fs-writeback.c:1827
writeback_sb_inodes+0x71c/0x1b60 fs/fs-writeback.c:2056
wb_writeback+0x404/0xbc0 fs/fs-writeback.c:2241
wb_do_writeback fs/fs-writeback.c:2388 [inline]
wb_workfn+0x158/0xbc0 fs/fs-writeback.c:2428
process_one_work+0x9dc/0x1c20 kernel/workqueue.c:3314
process_scheduled_works kernel/workqueue.c:3397 [inline]
worker_thread+0x693/0xea0 kernel/workqueue.c:3478
kthread+0x403/0x530 kernel/kthread.c:436
ret_from_fork+0xafe/0xda0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
-> #0 (&mft_ni_runlist_lock_key){++++}-{4:4}:
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x1616/0x26b0 kernel/locking/lockdep.c:5237
lock_acquire kernel/locking/lockdep.c:5868 [inline]
lock_acquire+0x1b0/0x350 kernel/locking/lockdep.c:5825
down_write+0x91/0x200 kernel/locking/rwsem.c:1625
ntfs_write_mft_block fs/ntfs/mft.c:2825 [inline]
ntfs_mft_writepages+0x1113/0x2410 fs/ntfs/mft.c:2955
do_writepages+0x242/0x5b0 mm/page-writeback.c:2571
__writeback_single_inode+0x127/0x1380 fs/fs-writeback.c:1764
writeback_sb_inodes+0x71c/0x1b60 fs/fs-writeback.c:2056
wb_writeback+0x404/0xbc0 fs/fs-writeback.c:2241
wb_do_writeback fs/fs-writeback.c:2388 [inline]
wb_workfn+0x158/0xbc0 fs/fs-writeback.c:2428
process_one_work+0x9dc/0x1c20 kernel/workqueue.c:3314
process_scheduled_works kernel/workqueue.c:3397 [inline]
worker_thread+0x693/0xea0 kernel/workqueue.c:3478
kthread+0x403/0x530 kernel/kthread.c:436
ret_from_fork+0xafe/0xda0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
other info that might help us debug this:
Chain exists of:
&mft_ni_runlist_lock_key --> &ni->extent_lock --> &extent_inode_mrec_lock_key
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&extent_inode_mrec_lock_key);
lock(&ni->extent_lock);
lock(&extent_inode_mrec_lock_key);
lock(&mft_ni_runlist_lock_key);
*** DEADLOCK ***
3 locks held by kworker/u9:5/4025:
#0: ff11000041ea0940 ((wq_completion)writeback){+.+.}-{0:0}, at: process_one_work+0x136f/0x1c20 kernel/workqueue.c:3289
#1: ffa00000110dfd08 ((work_completion)(&(&wb->dwork)->work)){+.+.}-{0:0}, at: process_one_work+0x936/0x1c20 kernel/workqueue.c:3290
#2: ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_may_write_mft_record fs/ntfs/mft.c:931 [inline]
#2: ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_write_mft_block fs/ntfs/mft.c:2788 [inline]
#2: ff110000239f1bf8 (&extent_inode_mrec_lock_key){+.+.}-{4:4}, at: ntfs_mft_writepages+0x1c6d/0x2410 fs/ntfs/mft.c:2955
stack backtrace:
CPU: 0 UID: 0 PID: 4025 Comm: kworker/u9:5 Tainted: G W 7.1.1 #1 PREEMPT(full)
Tainted: [W]=WARN
Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Workqueue: writeback wb_workfn (flush-7:0)
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1b0 lib/dump_stack.c:120
print_circular_bug+0x274/0x340 kernel/locking/lockdep.c:2043
check_noncircular+0x12d/0x150 kernel/locking/lockdep.c:2175
check_prev_add kernel/locking/lockdep.c:3165 [inline]
check_prevs_add kernel/locking/lockdep.c:3284 [inline]
validate_chain kernel/locking/lockdep.c:3908 [inline]
__lock_acquire+0x1616/0x26b0 kernel/locking/lockdep.c:5237
lock_acquire kernel/locking/lockdep.c:5868 [inline]
lock_acquire+0x1b0/0x350 kernel/locking/lockdep.c:5825
down_write+0x91/0x200 kernel/locking/rwsem.c:1625
ntfs_write_mft_block fs/ntfs/mft.c:2825 [inline]
ntfs_mft_writepages+0x1113/0x2410 fs/ntfs/mft.c:2955
do_writepages+0x242/0x5b0 mm/page-writeback.c:2571
Submission note:
This draft is for the public subsystem bug-report route. If you want to treat it as a security issue, do not send it to public lists; send it privately to the affected maintainers and Cc security@xxxxxxxxxx instead.
Artifacts available locally:
repro.prog
repro.cprog
repro.report
isolated_repro_status.safe.txt
Please let me know if you want the full syz repro, C repro, full dmesg/report, or kernel .config posted inline or sent as attachments.
Thanks,
Guikun Yang
Attachment:
repro.prog
Description: Binary data
Attachment:
repro.report
Description: Binary data
Attachment:
repro.cprog
Description: Binary data