ntfs: centalize $INDEX_ROOT header validation

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>
This commit is contained in:
Hyunchul Lee 2026-05-23 13:14:21 +09:00 committed by Namjae Jeon
parent 14bc34fe94
commit 8b97b302f5
3 changed files with 23 additions and 9 deletions

View 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)
{

View 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);

View File

@ -890,7 +890,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
*/
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 @@ static int ntfs_read_locked_inode(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(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;
}