diff --git a/include/ntfs-3g/mft.h b/include/ntfs-3g/mft.h index b6bf1875..9b17b26b 100644 --- a/include/ntfs-3g/mft.h +++ b/include/ntfs-3g/mft.h @@ -52,6 +52,9 @@ static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol, return ntfs_mft_records_read(vol, mref, 1, b); } +extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref, + MFT_RECORD *m); + extern int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref, MFT_RECORD **mrec, ATTR_RECORD **attr); diff --git a/libntfs-3g/mft.c b/libntfs-3g/mft.c index d4d280f8..7c633a98 100644 --- a/libntfs-3g/mft.c +++ b/libntfs-3g/mft.c @@ -209,6 +209,40 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref, return -1; } +int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref, + MFT_RECORD *m) +{ + ATTR_RECORD *a; + int ret = -1; + + if (!ntfs_is_file_record(m->magic)) { + ntfs_log_error("Record %llu has no FILE magic (0x%x)\n", + (unsigned long long)MREF(mref), *(le32 *)m); + goto err_out; + } + + if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) { + ntfs_log_error("Record %llu has corrupt allocation size " + "(%u <> %u)\n", (unsigned long long)MREF(mref), + vol->mft_record_size, + le32_to_cpu(m->bytes_allocated)); + goto err_out; + } + + a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset)); + if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) { + ntfs_log_error("Record %llu is corrupt\n", + (unsigned long long)MREF(mref)); + goto err_out; + } + + ret = 0; +err_out: + if (ret) + errno = EIO; + return ret; +} + /** * ntfs_file_record_read - read a FILE record from the mft from disk * @vol: volume to read from @@ -244,14 +278,13 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref, MFT_RECORD **mrec, ATTR_RECORD **attr) { MFT_RECORD *m; - ATTR_RECORD *a; - int err; if (!vol || !mrec) { errno = EINVAL; ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec); return -1; } + m = *mrec; if (!m) { m = ntfs_malloc(vol->mft_record_size); @@ -259,36 +292,26 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref, return -1; } if (ntfs_mft_record_read(vol, mref, m)) { - err = errno; ntfs_log_perror("ntfs_mft_record_read failed"); goto err_out; } - err = EIO; - if (!ntfs_is_file_record(m->magic)) { - ntfs_log_error("Record %llu has no FILE magic (0x%x)\n", - (unsigned long long)MREF(mref), *(le32 *)m); + if (ntfs_mft_record_check(vol, mref, m)) goto err_out; - } + if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) { ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n", (unsigned long long)MREF(mref), MSEQNO(mref), le16_to_cpu(m->sequence_number)); - goto err_out; - } - a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset)); - if (p2n(a) < p2n(m) || (char*)a > (char*)m + vol->mft_record_size) { - ntfs_log_error("Record %llu is corrupt\n", - (unsigned long long)MREF(mref)); + errno = EIO; goto err_out; } *mrec = m; if (attr) - *attr = a; + *attr = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset)); return 0; err_out: if (m != *mrec) free(m); - errno = err; return -1; } diff --git a/libntfs-3g/volume.c b/libntfs-3g/volume.c index c25e7442..fc680a6e 100644 --- a/libntfs-3g/volume.c +++ b/libntfs-3g/volume.c @@ -209,24 +209,14 @@ static int ntfs_mft_load(ntfs_volume *vol) ntfs_log_perror("Error reading $MFT"); goto error_exit; } - if (ntfs_is_baad_record(mb->magic)) { - ntfs_log_error("Incomplete multi sector transfer detected in " - "$MFT.\n"); - goto io_error_exit; - } - if (!ntfs_is_mft_record(mb->magic)) { - ntfs_log_error("$MFT has invalid magic.\n"); - goto io_error_exit; - } + + if (ntfs_mft_record_check(vol, 0, mb)) + goto error_exit; + ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL); if (!ctx) goto error_exit; - if (p2n(ctx->attr) < p2n(mb) || - (char*)ctx->attr > (char*)mb + vol->mft_record_size) { - ntfs_log_error("$MFT is corrupt.\n"); - goto io_error_exit; - } /* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */ if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {