summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryam Vargas <hexlabsecurity@proton.me>2026-07-26 18:29:11 -0500
committerNamjae Jeon <linkinjeon@kernel.org>2026-08-19 18:16:45 +0900
commit19cac7902a8ab748e15f98ddaafcf5f8882be21d (patch)
tree3f530ab202b592322c381a93a8e9e2ce271fd102
parent4d730a4dd78caa7bf29dda36fa5340a0237a8689 (diff)
downloadlinux-19cac7902a8ab748e15f98ddaafcf5f8882be21d.tar.gz
linux-19cac7902a8ab748e15f98ddaafcf5f8882be21d.zip
ntfs: bound the free-cluster bitmap scan to the volume
vol->lcn_empty_bits_per_page is sized from vol->nr_clusters at mount, but ntfs_cluster_alloc() bounds its scan of that array by the size of $Bitmap. Those are independent on-disk quantities and the mount-time check only rejects a $Bitmap that is too small, so an image whose $Bitmap covers more clusters than the volume has lets the scan index past the array. A run whose LCN lies in that gap takes the allocator straight there, since the caller passes the file's own last LCN as its locality hint. KASAN reports a slab out-of-bounds read when a file on such a volume is extended. Clamp the scan to what that array covers, mirroring the max_index calculation the mount-time scan already uses, and reject a decoded LCN at or beyond nr_clusters in the mapping pairs decoder. Conforming volumes are unaffected. Fixes: 11ccc9107dc4 ("ntfs: update runlist handling and cluster allocator") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r--fs/ntfs/lcnalloc.c7
-rw-r--r--fs/ntfs/runlist.c7
2 files changed, 13 insertions, 1 deletions
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 835a041023a2..aa2e017a4384 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -298,7 +298,12 @@ struct runlist_element *ntfs_cluster_alloc(struct ntfs_volume *vol, const s64 st
clusters = count;
rlpos = rlsize = 0;
mapping = lcnbmp_vi->i_mapping;
- i_size = i_size_read(lcnbmp_vi);
+ /*
+ * lcn_empty_bits_per_page is sized from nr_clusters, but $Bitmap can
+ * cover more clusters than that; bound the scan by the array.
+ */
+ i_size = min_t(s64, i_size_read(lcnbmp_vi),
+ ((s64)vol->nr_clusters + 7) >> 3);
while (1) {
ntfs_debug("Start of outer while loop: done_zones 0x%x, search_zone %i, pass %i, zone_start 0x%llx, zone_end 0x%llx, bmp_initial_pos 0x%llx, bmp_pos 0x%llx, rlpos %i, rlsize %i.",
done_zones, search_zone, pass,
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index 8e0fd400e7f7..17eb275a21ff 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -884,6 +884,13 @@ struct runlist_element *ntfs_mapping_pairs_decompress(const struct ntfs_volume *
ntfs_error(vol->sb, "lcn == -1");
}
#endif
+ /* Check lcn is within the volume. */
+ if (unlikely(lcn >= (s64)vol->nr_clusters)) {
+ ntfs_error(vol->sb,
+ "LCN >= nr_clusters in mapping pairs array.");
+ goto err_out;
+ }
+
/* Check lcn is not below -1. */
if (unlikely(lcn < -1)) {
ntfs_error(vol->sb, "Invalid s64 < -1 in mapping pairs array.");