Skip to content

Commit 013ff63

Browse files
fs/ntfs3: Add more attributes checks in mi_enum_attr()
Signed-off-by: Konstantin Komarov <[email protected]>
1 parent fc471e3 commit 013ff63

File tree

1 file changed

+52
-16
lines changed

1 file changed

+52
-16
lines changed

fs/ntfs3/record.c

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)