diff options
Diffstat (limited to 'fs/ntfs3/record.c')
-rw-r--r-- | fs/ntfs3/record.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c index 6c76503edc20..f810f0419d25 100644 --- a/fs/ntfs3/record.c +++ b/fs/ntfs3/record.c @@ -223,29 +223,21 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) prev_type = 0; attr = Add2Ptr(rec, off); } else { - /* Check if input attr inside record. */ + /* + * We don't need to check previous attr here. There is + * a bounds checking in the previous round. + */ off = PtrOffset(rec, attr); - if (off >= used) - return NULL; asize = le32_to_cpu(attr->size); - if (asize < SIZEOF_RESIDENT) { - /* Impossible 'cause we should not return such attribute. */ - return NULL; - } - - /* Overflow check. */ - if (off + asize < off) - return NULL; prev_type = le32_to_cpu(attr->type); attr = Add2Ptr(attr, asize); off += asize; } - asize = le32_to_cpu(attr->size); - /* Can we use the first field (attr->type). */ + /* NOTE: this code also checks attr->size availability. */ if (off + 8 > used) { static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8); return NULL; @@ -265,6 +257,8 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) if (t32 < prev_type) return NULL; + asize = le32_to_cpu(attr->size); + /* Check overflow and boundary. */ if (off + asize < off || off + asize > used) return NULL; @@ -293,6 +287,10 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) if (attr->non_res != 1) return NULL; + /* Can we use memory including attr->nres.valid_size? */ + if (asize < SIZEOF_NONRESIDENT) + return NULL; + t16 = le16_to_cpu(attr->nres.run_off); if (t16 > asize) return NULL; @@ -319,7 +317,8 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) if (!attr->nres.svcn && is_attr_ext(attr)) { /* First segment of sparse/compressed attribute */ - if (asize + 8 < SIZEOF_NONRESIDENT_EX) + /* Can we use memory including attr->nres.total_size? */ + if (asize < SIZEOF_NONRESIDENT_EX) return NULL; tot_size = le64_to_cpu(attr->nres.total_size); @@ -329,10 +328,10 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) if (tot_size > alloc_size) return NULL; } else { - if (asize + 8 < SIZEOF_NONRESIDENT) + if (attr->nres.c_unit) return NULL; - if (attr->nres.c_unit) + if (alloc_size > mi->sbi->volume.size) return NULL; } |