[PATCH v2] ntfs: reject invalid MFT LCNs from boot sector

Hyunchul Lee posted 1 patch 1 month, 1 week ago
fs/ntfs/super.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
[PATCH v2] ntfs: reject invalid MFT LCNs from boot sector
Posted by Hyunchul Lee 1 month, 1 week ago
The NTFS boot sector stores the MFT and MFTMirr locations as unsigned
64-bit LCNs, but parse_ntfs_boot_sector() decoded them into an s64.
A crafted high-bit value could therefore become negative and pass
the existing upper-bound check. The invalid value then propagated into
the MFT zone allocator and could result in an out-of-bounds access to
lcn_empty_bits_per_page.

Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
Reported-by: Robert Morris <rtm@csail.mit.edu>
Closes: https://lore.kernel.org/all/57514.1787000602@localhost
Cc: stable@vger.kernel.org
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
---
Changes in v2:
  * Change the pr_error format from "%lli" to "llu".
  * Add Reported-by tag.

 fs/ntfs/super.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 8abe7bee4c0d..cd8fa2c13370 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -645,7 +645,7 @@ static bool parse_ntfs_boot_sector(struct ntfs_volume *vol,
 {
 	unsigned int sectors_per_cluster, sectors_per_cluster_bits, nr_hidden_sects;
 	int clusters_per_mft_record, clusters_per_index_record;
-	s64 ll;
+	u64 ll;
 
 	vol->sector_size = le16_to_cpu(b->bpb.bytes_per_sector);
 	vol->sector_size_bits = ffs(vol->sector_size) - 1;
@@ -755,23 +755,23 @@ static bool parse_ntfs_boot_sector(struct ntfs_volume *vol,
 	 * the same as it is much faster on 32-bit CPUs.
 	 */
 	ll = le64_to_cpu(b->number_of_sectors) >> sectors_per_cluster_bits;
-	if ((u64)ll >= 1ULL << 32) {
+	if (ll >= 1ULL << 32) {
 		ntfs_error(vol->sb, "Cannot handle 64-bit clusters.");
 		return false;
 	}
 	vol->nr_clusters = ll;
 	ntfs_debug("vol->nr_clusters = 0x%llx", vol->nr_clusters);
 	ll = le64_to_cpu(b->mft_lcn);
-	if (ll >= vol->nr_clusters) {
-		ntfs_error(vol->sb, "MFT LCN (%lli, 0x%llx) is beyond end of volume.  Weird.",
+	if (ll >= (u64)vol->nr_clusters) {
+		ntfs_error(vol->sb, "MFT LCN (%llu, 0x%llx) is beyond end of volume.  Weird.",
 				ll, ll);
 		return false;
 	}
 	vol->mft_lcn = ll;
 	ntfs_debug("vol->mft_lcn = 0x%llx", vol->mft_lcn);
 	ll = le64_to_cpu(b->mftmirr_lcn);
-	if (ll >= vol->nr_clusters) {
-		ntfs_error(vol->sb, "MFTMirr LCN (%lli, 0x%llx) is beyond end of volume.  Weird.",
+	if (ll >= (u64)vol->nr_clusters) {
+		ntfs_error(vol->sb, "MFTMirr LCN (%llu, 0x%llx) is beyond end of volume.  Weird.",
 				ll, ll);
 		return false;
 	}

---
base-commit: df7dce2090342170b7643d36f694204cae7792a9
change-id: 20260818-fix-negative-mft-lcn-596257dd23c8

Best regards,
-- 
Thanks,
Hyunchul

Re: [PATCH v2] ntfs: reject invalid MFT LCNs from boot sector
Posted by Namjae Jeon 1 month, 1 week ago
On Wed, Aug 19, 2026 at 4:19 PM Hyunchul Lee <hyc.lee@gmail.com> wrote:
>
> The NTFS boot sector stores the MFT and MFTMirr locations as unsigned
> 64-bit LCNs, but parse_ntfs_boot_sector() decoded them into an s64.
> A crafted high-bit value could therefore become negative and pass
> the existing upper-bound check. The invalid value then propagated into
> the MFT zone allocator and could result in an out-of-bounds access to
> lcn_empty_bits_per_page.
>
> Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator")
> Reported-by: Robert Morris <rtm@csail.mit.edu>
> Closes: https://lore.kernel.org/all/57514.1787000602@localhost
> Cc: stable@vger.kernel.org
> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Applied it to #ntfs-next.
Thanks!