fs/ntfs/super.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
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
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!
© 2016 - 2026 Red Hat, Inc.