aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
Diffstat (limited to 'fs')
-rw-r--r--fs/ntfs/index.c18
-rw-r--r--fs/ntfs/index.h3
-rw-r--r--fs/ntfs/inode.c11
3 files changed, 23 insertions, 9 deletions
diff --git a/fs/ntfs/index.c b/fs/ntfs/index.c
index 9713b082b03df..97c0e7d6a580b 100644
--- a/fs/ntfs/index.c
+++ b/fs/ntfs/index.c
@@ -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)
{
diff --git a/fs/ntfs/index.h b/fs/ntfs/index.h
index 3451ec8a1c4eb..cad78568d8b35 100644
--- a/fs/ntfs/index.h
+++ b/fs/ntfs/index.h
@@ -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);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 360bebd1ee3fe..63ee7acff4fc9 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -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;
}