fix crash when both an mft attribute offset and the allocated bytes were corrupt

master
szaka 2008-05-23 20:33:27 +00:00
parent 78915c1d3c
commit 9d6a1dc617
3 changed files with 46 additions and 30 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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)) {