]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ntfs: centalize $INDEX_ROOT header validation
authorHyunchul Lee <hyc.lee@gmail.com>
Sat, 23 May 2026 04:14:21 +0000 (13:14 +0900)
committerNamjae Jeon <linkinjeon@kernel.org>
Fri, 5 Jun 2026 15:19:54 +0000 (00:19 +0900)
Add a dedicated helper to perform stricter validation of $INDEX_ROOT and
use it for both directory inodes and named index inodes. This keeps the
root size and header geometry checks consistent across both read paths.

Cc: stable@vger.kernel.org # v7.1
Tested-by: woot000 <woot000@woot000.com>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
fs/ntfs/index.c
fs/ntfs/index.h
fs/ntfs/inode.c

index 9713b082b03df3c5b4a20ba2ff9421cbc379a740..97c0e7d6a580bf96396c3c91f2907b9bb288122e 100644 (file)
@@ -541,6 +541,24 @@ int ntfs_index_block_inconsistent(struct ntfs_volume *vol,
        return 0;
 }
 
+int ntfs_index_root_inconsistent(struct ntfs_volume *vol,
+                                const struct attr_record *a,
+                                const struct index_root *ir, u64 inum)
+{
+       u32 value_length = le32_to_cpu(a->data.resident.value_length);
+
+       if (value_length < offsetof(struct index_root, index)) {
+               ntfs_error(vol->sb, "$INDEX_ROOT in inode %llu is too small.",
+                          (unsigned long long)inum);
+               return -EIO;
+       }
+
+       return ntfs_index_header_inconsistent(vol, &ir->index,
+                                             value_length -
+                                             offsetof(struct index_root, index),
+                                             inum);
+}
+
 static struct index_root *ntfs_ir_lookup(struct ntfs_inode *ni, __le16 *name,
                u32 name_len, struct ntfs_attr_search_ctx **ctx)
 {
index 3451ec8a1c4eb794d2d568a0ee84050b54adbf43..cad78568d8b350f99158d8b520064e0e6715d903 100644 (file)
@@ -89,6 +89,9 @@ struct ntfs_index_context {
        bool sync_write;
 };
 
+int ntfs_index_root_inconsistent(struct ntfs_volume *vol,
+                                const struct attr_record *a,
+                                const struct index_root *ir, u64 inum);
 int ntfs_index_block_inconsistent(struct ntfs_volume *vol,
                                  const struct index_block *ib,
                                  u32 block_size, s64 vcn, u64 inum);
index 360bebd1ee3fe61cf94f0be9c7984b3949e1d274..63ee7acff4fc92963092c03b0ab7b35d66ac8d61 100644 (file)
@@ -890,7 +890,6 @@ skip_attr_list_load:
         */
        if (S_ISDIR(vi->i_mode)) {
                struct index_root *ir;
-               u8 *ir_end, *index_end;
 
 view_index_meta:
                /* It is a directory, find index root attribute. */
@@ -940,10 +939,7 @@ view_index_meta:
                }
                ir = (struct index_root *)((u8 *)a +
                                le16_to_cpu(a->data.resident.value_offset));
-               ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length);
-               index_end = (u8 *)&ir->index +
-                               le32_to_cpu(ir->index.index_length);
-               if (index_end > ir_end) {
+               if (ntfs_index_root_inconsistent(ni->vol, a, ir, ni->mft_no)) {
                        ntfs_error(vi->i_sb, "Directory index is corrupt.");
                        goto unm_err_out;
                }
@@ -1483,7 +1479,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
        struct attr_record *a;
        struct ntfs_attr_search_ctx *ctx;
        struct index_root *ir;
-       u8 *ir_end, *index_end;
        int err = 0;
 
        ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no);
@@ -1534,9 +1529,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
        }
 
        ir = (struct index_root *)((u8 *)a + le16_to_cpu(a->data.resident.value_offset));
-       ir_end = (u8 *)ir + le32_to_cpu(a->data.resident.value_length);
-       index_end = (u8 *)&ir->index + le32_to_cpu(ir->index.index_length);
-       if (index_end > ir_end) {
+       if (ntfs_index_root_inconsistent(vol, a, ir, ni->mft_no)) {
                ntfs_error(vi->i_sb, "Index is corrupt.");
                goto unm_err_out;
        }