CVE-2026-72203: ntfs: skip extent mft records in writeback to prevent deadlock
In the Linux kernel, the following vulnerability has been resolved:
ntfs: skip extent mft records in writeback to prevent deadlock
This patch fixes the ABBA deadlock between extentlock and extent mreclock triggered by xfstests generic/113, that occurs since the commit 6994acf33bae ("ntfs: use base mftno when looking up base inode for extent record").
Path A (inode writeback): VFS writeback -> ntfswriteinode() -> ntfswriteinode() -> mutexlock(&ni->extentlock) -> mutexlock(&tni->mreclock)
Path B (MFT folio writeback): VFS writeback of $MFT dirty folios -> ntfsmftwritepages() -> ntfswritemftblock() -> ntfsmaywritemftrecord() -> holds one extent mreclock from a previous iteration -> tries to acquire another base inode extentlock
By removing all extentlock and extent mreclock acquisition from the MFT folio writeback path, the ABBA lock ordering is eliminated:
Path A: ntfswriteinode(): extentlock -> mreclock Path B (removed): ntfswritemftblock(): mreclock -> extentlock
Path B is always redundant for extent records because:
1. markmftrecorddirty(extni) does NOT dirty the MFT folio. It only sets NInoDirty(extni) and marks the base VFS inode dirty via markinodedirty(IDIRTYDATASYNC), which triggers Path A. Therefore, normal extent modifications never create a situation where the MFT folio is dirty and Path B is not scheduled.
2. The MFT folio only gets dirtied via ntfsmftmarkdirty() inside ntfsmftrecordalloc(). But all identified callers in attrib.c (ntfsattradd, ntfsattrrecordmoveaway, ntfsattrmakenonresident, ntfsattrrecordresize) follow through with markmftrecorddirty(), which triggers Path A to write the complete record.
3. ntfsevictbiginode() calls ntfscommitinode() before freeing extent inodes, ensuring all dirty extents are flushed via Path A before the base inode leaves the icache.