@@ -193,8 +193,9 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
193193{
194194 const struct MFT_REC * rec = mi -> mrec ;
195195 u32 used = le32_to_cpu (rec -> used );
196- u32 t32 , off , asize ;
196+ u32 t32 , off , asize , prev_type ;
197197 u16 t16 ;
198+ u64 data_size , alloc_size , tot_size ;
198199
199200 if (!attr ) {
200201 u32 total = le32_to_cpu (rec -> total );
@@ -213,6 +214,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
213214 if (!is_rec_inuse (rec ))
214215 return NULL ;
215216
217+ prev_type = 0 ;
216218 attr = Add2Ptr (rec , off );
217219 } else {
218220 /* Check if input attr inside record. */
@@ -226,11 +228,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
226228 return NULL ;
227229 }
228230
229- if ( off + asize < off ) {
230- /* Overflow check. */
231+ /* Overflow check. */
232+ if ( off + asize < off )
231233 return NULL ;
232- }
233234
235+ prev_type = le32_to_cpu (attr -> type );
234236 attr = Add2Ptr (attr , asize );
235237 off += asize ;
236238 }
@@ -250,7 +252,11 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
250252
251253 /* 0x100 is last known attribute for now. */
252254 t32 = le32_to_cpu (attr -> type );
253- if ((t32 & 0xf ) || (t32 > 0x100 ))
255+ if (!t32 || (t32 & 0xf ) || (t32 > 0x100 ))
256+ return NULL ;
257+
258+ /* attributes in record must be ordered by type */
259+ if (t32 < prev_type )
254260 return NULL ;
255261
256262 /* Check overflow and boundary. */
@@ -259,16 +265,15 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
259265
260266 /* Check size of attribute. */
261267 if (!attr -> non_res ) {
268+ /* Check resident fields. */
262269 if (asize < SIZEOF_RESIDENT )
263270 return NULL ;
264271
265272 t16 = le16_to_cpu (attr -> res .data_off );
266-
267273 if (t16 > asize )
268274 return NULL ;
269275
270- t32 = le32_to_cpu (attr -> res .data_size );
271- if (t16 + t32 > asize )
276+ if (t16 + le32_to_cpu (attr -> res .data_size ) > asize )
272277 return NULL ;
273278
274279 t32 = sizeof (short ) * attr -> name_len ;
@@ -278,21 +283,52 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
278283 return attr ;
279284 }
280285
281- /* Check some nonresident fields. */
282- if (attr -> name_len &&
283- le16_to_cpu (attr -> name_off ) + sizeof (short ) * attr -> name_len >
284- le16_to_cpu (attr -> nres .run_off )) {
286+ /* Check nonresident fields. */
287+ if (attr -> non_res != 1 )
288+ return NULL ;
289+
290+ t16 = le16_to_cpu (attr -> nres .run_off );
291+ if (t16 > asize )
292+ return NULL ;
293+
294+ t32 = sizeof (short ) * attr -> name_len ;
295+ if (t32 && le16_to_cpu (attr -> name_off ) + t32 > t16 )
296+ return NULL ;
297+
298+ /* Check start/end vcn. */
299+ if (le64_to_cpu (attr -> nres .svcn ) > le64_to_cpu (attr -> nres .evcn ) + 1 )
300+ return NULL ;
301+
302+ data_size = le64_to_cpu (attr -> nres .data_size );
303+ if (le64_to_cpu (attr -> nres .valid_size ) > data_size )
285304 return NULL ;
286- }
287305
288- if (attr -> nres .svcn || !is_attr_ext (attr )) {
306+ alloc_size = le64_to_cpu (attr -> nres .alloc_size );
307+ if (data_size > alloc_size )
308+ return NULL ;
309+
310+ t32 = mi -> sbi -> cluster_mask ;
311+ if (alloc_size & t32 )
312+ return NULL ;
313+
314+ if (!attr -> nres .svcn && is_attr_ext (attr )) {
315+ /* First segment of sparse/compressed attribute */
316+ if (asize + 8 < SIZEOF_NONRESIDENT_EX )
317+ return NULL ;
318+
319+ tot_size = le64_to_cpu (attr -> nres .total_size );
320+ if (tot_size & t32 )
321+ return NULL ;
322+
323+ if (tot_size > alloc_size )
324+ return NULL ;
325+ } else {
289326 if (asize + 8 < SIZEOF_NONRESIDENT )
290327 return NULL ;
291328
292329 if (attr -> nres .c_unit )
293330 return NULL ;
294- } else if (asize + 8 < SIZEOF_NONRESIDENT_EX )
295- return NULL ;
331+ }
296332
297333 return attr ;
298334}
0 commit comments