CVE-2026-90131
HighCVSS 7.1Exploitation Probability (EPSS)
Low risk5th percentile - higher than 5% of all known CVEs
Summary
In the Linux kernel NTFS module, ntfs_read_iomap_begin_resident() reads an MFT record without holding ni->mrec_lock, while other functions modify the same buffer under that lock. This causes a data race and allows reading torn attribute length and offset fields. The issue was fixed by holding mrec_lock from the resident iomap read lookup through iomap_end().
Risk Assessment
The data race can cause data corruption or incorrect reads on NTFS filesystems, potentially leading to kernel instability or application errors. The risk mainly occurs when mmap reads run concurrently with link()/unlink() operations on the same file.
Recommendation
Update the Linux kernel to a version containing the fix for CVE-2026-90131. If updating is not possible, avoid concurrent link()/unlink() operations on NTFS files while they are being read via mmap.
Other vulnerabilities in Linux kernel NTFS
See all- CVE-2026-98141Unknown
In the Linux kernel, update_reparse_data() in the ntfs driver ignores the return value of set_reparse_index(). When index insertion fails, the code removes the just-written reparse data as cleanup but still returns 0, so symlink(2) reports success while no reparse data exists on disk.
- CVE-2026-98140Unknown
In the Linux kernel, write_mft_record_nolock() in the ntfs driver maps the MFT record folio with kmap_local_folio(), but the pre_write_mst_fixup() and bio_add_folio() failure paths jump to the error label without unmapping it. Since kmap_local mappings are stack-ordered per task, leaking one corrupts the nesting for any outer mapping.
- CVE-2026-98139Unknown
In the Linux kernel, ntfs_cluster_free_from_rl_nolock() in the ntfs driver adds a run's length to nr_freed whenever the error bookkeeping condition is false, which includes cases where ntfs_bitmap_clear_run() actually failed. Since a failed ntfs_bitmap_clear_run() rolls back its partial modifications, no bits were cleared for that run, yet its length still inflates vol->free_clusters.
- CVE-2026-98138Unknown
In the Linux kernel, ntfs_sync_fs() in the ntfs driver unconditionally clears the dirty bit, whereas ntfs_put_super() and the remount-read-only path only clear it when NVolErrors(vol) is false. As a result, any sync() on a volume that recorded an error marks that volume clean, so no recovery is run.
- CVE-2026-98137Unknown
In the Linux kernel, ntfs_dio_zero_range() in the ntfs driver returns either 0 or a negative errno from blkdev_issue_zeroout(); it never returns a positive value. The zeroing failure check in ntfs_attr_fallocate() therefore never fired, so a failed zeroing operation was silently ignored and newly allocated clusters were folded into initialized_size.
- CVE-2026-98136Unknown
In the Linux kernel, ntfs_attr_find_in_attrdef() in the ntfs driver walks the in-memory $AttrDef table, but the loop condition bounds only the start of each entry, not the whole entry. A volume whose $AttrDef data size is smaller than one entry (e.g. 120 bytes) causes an out-of-bounds read when creating a file.
- CVE-2026-98135Unknown
In the Linux kernel, is_boot_sector_ntfs() in the ntfs driver checks the boot sector's sectors_per_cluster field with a range test that rejects 0x81..0xf3 but accepts 0 and other non-power-of-two counts. A zero value reaches parse_ntfs_boot_sector(), where ffs(0) is 0, making the shift undefined.
- CVE-2026-98133Unknown
In the Linux kernel, ntfs_set_ea() in the ntfs driver unconditionally updates the HasEA flag based on ea_info_qsize in its exit path. When an error occurs before ea_info_qsize is updated, NInoClearHasEA() hides existing on-disk extended attributes (EAs) until the inode is evicted.
- CVE-2026-89614Critical
In the Linux kernel, the ntfs driver bounds its free-cluster bitmap scan by the size of $Bitmap rather than the volume's cluster count. An image whose $Bitmap covers more clusters than the volume allows indexing past the lcn_empty_bits_per_page array.
- CVE-2026-89613Critical
In the Linux kernel, the ntfs driver does not reject attributes with empty mapping pairs if they have inconsistent highest VCN and size. The lack of validation can lead to incorrect processing.
Original NVD description (English source)
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.
Vulnerability data from NVD (NIST) · CISA KEV · EPSS

