Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the NTFS $MFT file have child records?

I am writing some code to parse through the MFT on disk in NTFS volumes. This is straightforward, but one particular corner case caught my eye, and I can't find a clear answer anywhere on the internet.

For normal files in NTFS it is possible to have multiple MFT records for a single file, if the file has more attributes than can fit in a single record (for example, many $FILE_NAME attributes if the file has many hard-links, or many $DATA attributes if it has many Alternate Data Streams).

The $MFT file at reference-number 0 holds the data runs for the MFT itself. Normally it is a single record with no children. Is it possible for the $MFT file to have child records? If it were possible, how would you know where to find them? Would those child records have to be stored with very low reference numbers so that you could reliably get to them without having to have parsed the $MFT already to know where they were on disk?

like image 302
DSII Avatar asked May 24 '15 13:05

DSII


2 Answers

There is a special type of attribute called $ATTRIBUTE_LIST. A file or directory can have up to 65536 attributes and they can't possibly fit into a single MFT entry. It basically contains a list of all the file's attributes except himself. Each entry in the list contains the attribute type and the MFT reference of where to find the attribute. That's what the base file reference field in the file record header is for.

If the list gets too big for a MFT entry, the attribute can become non-resident and the list will be found by interpreting the data run of the attribute.

Because the type of the $ATTRIBUTE_LIST is 32, it's placed usually right after the $STANDARD_INFORMATION attribute and will contain attributes with greater types (like $FILE_NAME or $DATA).

When a file becomes very fragmented, the $DATA attribute run list will not fit in a single MFT entry. This is also a case where $ATTRIBUTE_LIST will be used to store the $DATA attribute in multiple entries.

The $MFT entry rarely has this problem since the allocation alogrithm is designed to prevent that. But if a $MFT for a volume becomes very fragmented it can have more than one entry to store it's $DATA.

like image 175
Sebastian-Laurenţiu Plesciuc Avatar answered Sep 22 '22 17:09

Sebastian-Laurenţiu Plesciuc


tl;dr: Yes; I believe this is what ERROR_DISK_TOO_FRAGMENTED/STATUS_MFT_TOO_FRAGMENTED are for.

To elaborate:

The MFT file can most certainly have child records. If you need to construct one like this, just open \$MFT (do it on a RAM disk unless you want to mess up a physical volume...) and then FSCTL_MOVE_FILE each entry, alternating between the beginning and the end of the volume. You'll severely fragment the MFT and cause it to generate an $ATTRIBUTE_LIST, such that it won't even fit into the last 4 of the 16 initial records anymore. It'll overflow into later slots.

Logic dictates, however, that the MFT needs to be bootstrappable. Thus I can only conclude each child described by an $ATTRIBUTE_LIST entry must be in a slot from a previous extent. As such, it is possible to run into a situation where the volume has enough free space to grow the MFT, but no free slots to describe the MFT's next extent. I think this is one situation where the driver would return STATUS_MFT_TOO_FRAGMENTED.

Good luck writing an efficient parser for this, it's rather tedious.

(n.b. It's possible but harder to fragment the $ATTRIBUTE_LIST itself too. But I read that its run-list must fit within a single record, so this imposes a hard limit on the number of fragments.)

like image 23
user541686 Avatar answered Sep 25 '22 17:09

user541686