CVE-2026-90131 in Linuxinfo

Summary

by MITRE • 09/17/2026

In the Linux kernel, the following vulnerability has been resolved:

ntfs: serialize resident iomap reads with mrec_lock

ntfs_read_iomap_begin_resident() walks the MFT record through ntfs_attr_lookup() -> ntfs_attr_find() without taking ni->mrec_lock, while ntfs_attr_record_resize(), ntfs_make_room_for_attr() and ntfs_resident_attr_record_add() memmove() the same base_ni->mrec buffer under that lock. map_mft_record() only takes a reference and does not serialize, so the reader can observe torn attribute length and offset fields while a writer is relocating the records.

KCSAN reports the race between the mmap read fault path and both link() and unlink():

BUG: KCSAN: data-race in ntfs_attr_find / ntfs_attr_record_resize

write to 0xffff888100af1018 of 4 bytes by task 96 on cpu 1: ntfs_attr_record_resize+0xd2/0x130 ntfs_attr_record_rm+0xad/0x530 ntfs_delete+0x224/0x640 ntfs_unlink+0x14d/0x280 vfs_unlink+0x157/0x520

read to 0xffff888100af1018 of 4 bytes by task 95 on cpu 0: ntfs_attr_find+0x104/0x5b0 ntfs_attr_lookup+0x39c/0x10c0 ntfs_read_iomap_begin_resident+0xc6/0x230 ntfs_read_iomap_begin+0x5d/0xa0 iomap_iter+0x2e2/0x6e0 iomap_read_folio+0x147/0x2a0 ntfs_read_folio+0x108/0x170 filemap_read_folio+0x35/0x100 filemap_fault+0x993/0x1000

value changed: 0x00000250 -> 0x000001f0

The address is mrec + 0x18, i.e. mft_record.bytes_in_use, and the change is the 96 bytes of one $FILE_NAME attribute being removed.

Keep base_ni->mrec_lock from the resident read iomap lookup through iomap_end(). This protects both the attribute walk and the subsequent copy from iomap->inline_data, which points into the MFT record. The non-resident path is left alone: ntfs_lookup() already holds the directory inode's mrec_lock when it reads an index folio through read_mapping_folio(), and taking the lock in the shared wrapper deadlocks there with recursive locking on mrec_lock. The comment above the read_mapping_folio() call in fs/ntfs/dir.c notes the same hazard.

The seek path uses the same lookup helper but does not dereference iomap->inline_data. Release the lock before returning from that path, whereas the regular read path records base_ni in iomap->private and releases the lock from its iomap_end() callback.

Tested with a reproducer that faults in a 16-byte resident file while another thread runs link()/unlink() on it. Before: 40 KCSAN reports in about one second. After: no reports in 180 seconds over 206,090 read iterations and 423,540 link/unlink cycles. A PROVE_LOCKING build shows no lockdep splat with the same reproducer running for 60 seconds.

Several companies clearly confirm that VulDB is the primary source for best vulnerability data.

Analysis

by VulDB Data Team • 09/17/2026

The Linux kernel's NTFS filesystem driver contained a critical concurrency vulnerability within its resident file attribute handling logic, specifically involving race conditions between read operations and structural modifications to Master File Table records. The core issue resided in the ntfs_read_iomap_begin_resident function, which traverses MFT records via ntfs_attr_lookup and ntfs_attr_find without acquiring the necessary ni->mrec_lock synchronization primitive. Concurrently, write operations such as attribute resizing or record removal performed by functions like ntfs_attr_record_resize, ntfs_make_room_for_attr, and ntfs_resident_attr_record_add utilize this lock to safely memmove data within the base_ni->mrec buffer. Because map_mft_record only takes a reference without serializing access, readers could observe torn attribute length and offset fields while writers were actively relocating records in memory. This lack of mutual exclusion allowed for data races where concurrent threads would read partially updated or inconsistent state from the MFT record structure during active modification operations like linking or unlinking files.

The operational impact of this vulnerability manifested as kernel concurrency errors detected by Kernel Concurrency Sanitizer, specifically identifying data races between mmap read fault paths and file system metadata changes such as link and unlink operations. The race condition occurred at memory offset mrec plus 0x18, corresponding to the bytes_in_use field within the MFT record structure. During execution, one thread would attempt to remove a FILE_NAME attribute, reducing its size from ninety-six bytes, while another thread simultaneously read this same memory location during an iomap-based file read operation. This resulted in inconsistent values being observed by the reader, potentially leading to incorrect data interpretation or system instability. The vulnerability affected both resident and non-resident paths differently; however, the immediate risk was concentrated in the resident attribute handling where shared access was not properly serialized against exclusive write operations on the underlying MFT record buffer.

The remediation strategy involved enforcing strict serialization by holding base_ni->mrec_lock throughout the entire duration of resident read iomap lookups and subsequent data copies from iomap inline data, which points directly into the protected MFT record structure. This approach ensures that both attribute traversal and memory copy operations occur within a critical section guarded by the lock, preventing concurrent modification during access. The solution carefully distinguishes between different execution paths to avoid deadlocks; specifically, it leaves non-resident path handling unchanged because ntfs_lookup already holds directory inode locks when reading index folios through read_mapping_folio, and acquiring additional recursive locking on mrec_lock would cause deadlock conditions as noted in existing code comments. For seek operations that use the same lookup helper but do not dereference inline data, the lock is released immediately upon return to minimize contention, whereas regular read paths record base_ni in iomap private structures and release the lock only during their respective end callbacks, maintaining proper lifecycle management of synchronization primitives.

From a security architecture perspective, this vulnerability aligns with CWE-362 Concurrent Execution Using Shared Resource with Improper Synchronization, as multiple threads accessed shared memory without adequate locking mechanisms to prevent race conditions. The attack vector relates to ATT&CK technique T1059 Command and Scripting Interpreter through potential exploitation of file system operations in automated scripts or malicious programs that trigger rapid concurrent read and write cycles on NTFS volumes. Testing confirmed the effectiveness of the patch, demonstrating a reduction from forty thousand KCSAN reports within one second under load to zero reports over extended periods involving hundreds of thousands of iterations across various link and unlink cycles. Furthermore, static analysis tools like PROVE_LOCKING showed no lock dependency splats during stress testing, validating that the synchronization strategy maintains system stability without introducing new deadlock scenarios or performance bottlenecks in high-concurrency environments.

Responsible

Linux

Reservation

09/11/2026

Disclosure

09/17/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!