From b249246e9f00085c501c28112f6a8939a517e676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Fri, 17 Apr 2015 10:41:04 +0200 Subject: [PATCH] Defended against reusing data from an invalid MFT record An unused MFT record may show a bad length, leading to fetch fixups from unallocated memory when allocating the record to a new file. So check the length before applying the fixups. Such records have been found after the MFT has been reallocated by a defragmenter, and they are not cleaned by chkdsk. --- libntfs-3g/mft.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libntfs-3g/mft.c b/libntfs-3g/mft.c index ac4c610b..af10ffdd 100644 --- a/libntfs-3g/mft.c +++ b/libntfs-3g/mft.c @@ -5,7 +5,7 @@ * Copyright (c) 2004-2005 Richard Russon * Copyright (c) 2004-2008 Szabolcs Szakacsits * Copyright (c) 2005 Yura Pakhuchiy - * Copyright (c) 2014 Jean-Pierre Andre + * Copyright (c) 2014-2015 Jean-Pierre Andre * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -1628,6 +1628,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni) MFT_RECORD *m; ntfs_inode *ni = NULL; int err; + u32 usa_ofs; le16 seq_no, usn; if (base_ni) @@ -1754,7 +1755,16 @@ found_free_rec: goto retry; } seq_no = m->sequence_number; - usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); + /* + * As ntfs_mft_record_read() returns what has been read + * even when the fixups have been found bad, we have to + * check where we fetch the initial usn from. + */ + usa_ofs = le16_to_cpu(m->usa_ofs); + if (!(usa_ofs & 1) && (usa_ofs < NTFS_BLOCK_SIZE)) { + usn = *(le16*)((u8*)m + usa_ofs); + } else + usn = const_cpu_to_le16(1); if (ntfs_mft_record_layout(vol, bit, m)) { ntfs_log_error("Failed to re-format mft record.\n"); free(m);