fix crash when both an mft attribute offset and the allocated bytes were corrupt
parent
78915c1d3c
commit
9d6a1dc617
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue