FAQ SearchLogin
Tuxera Home
View unanswered posts | View active topics It is currently Wed May 12, 2021 00:52



Post new topic Reply to topic  [ 6 posts ] 
[BUG] ntfs_attr_open() may read beyond end of MFT record buf 
Author Message

Joined: Fri Aug 24, 2012 21:18
Posts: 30
Post [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Hi,

After making some changes to my code that uses libntfs-3g, I found that valgrind would occasionally generate a warning regarding an invalid memory access on line 457 of libntfs-3g/attrib.c in ntfs_attr_open() (accessing 8 bytes past a buffer allocated at line 1704 of mft.c). Line numbers in 2013.1.13 release. This error seemed to happen in a specific case when opening the unnamed data stream of a file with about 7 hard links.

As far as I can tell, the invalid memory access happens because ntfs_attr_open() will attempt to access 'initialized_size' of the attribute record, which is only valid when the attribute is non-resident:

Code:
        if ((type == AT_DATA) && !a->initialized_size) {


I attached the output of 'ntfsinfo -F' for a visible example that was as minimal as I could find. It looks like the unnamed $DATA attribute is towards the end of the MFT record and is resident, so when ntfs_attr_open() assumes it is nonresident this can read off the end of the MFT record buffer. To reproduce this problem one can create a file "ntfs.img" containing an empty NTFS, then add an empty file "A" in the root directory with 7 additional hard links named "1" through "7" to the same file; then run the C program I attached (with valgrind).

Also, while I was trying to track down this bug I thought that the following code in ntfs_external_attr_find() (from attrib.c:3155) was somewhat questionable:

Code:
do_next_attr_loop:
   if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec +
         le32_to_cpu(ctx->mrec->bytes_allocated))
      break;


It appears to check for cases where the length of an attribute record overflows the MFT entry, but it only checks for 0 bytes of room before attempting to access the ATTR_RECORD at that location. But, that would be a different bug and would only cause problems on corrupt filesystems. (The same issue seems to appear in ntfs_attr_find()...)

I hope this is helpful; I could send patches but this was the first time I was really taking a look at this code in detail.


Attachments:
ntfsinfo.txt.gz [893 Bytes]
Downloaded 896 times
test.c.gz [374 Bytes]
Downloaded 839 times
Thu Aug 15, 2013 09:36
Profile
NTFS-3G Lead Developer

Joined: Tue Sep 04, 2007 17:22
Posts: 1286
Post Re: [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Hi,

Thank you for reporting the abnormal condition and possible bug.

Quote:
This error seemed to happen in a specific case when opening the unnamed data stream of a file with about 7 hard links.

In the MFT record you posted, there is a strange void $ATTRIBUTE_LIST. This is normally only present when the MFT record overflows and an extent is needed.
When I try to recreate a similar file, I do get an $ATTRIBUTE_LIST, and one of the names is put into an extent, so the sequence of actions (libntfs-3g calls) you used to create the file might be meaningful. Can you post them ?

I will look at this later, when I have more spare time.

Regards

Jean-Pierre


Thu Aug 15, 2013 10:47
Profile

Joined: Fri Aug 24, 2012 21:18
Posts: 30
Post Re: [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Hi,

Although I originally noticed this problem when using libntfs-3g directly to create the files, I found that the problem could also be reproduced by creating the files on a FUSE-mounted NTFS volume. Furthermore, following that, the invalid memory access can be made by ntfs-3g during the same FUSE mount, without any external code using libntfs-3g (unlike what I posted before). For example, I found that the problem could be reproduced by running this in an empty directory:

Code:
dd if=/dev/zero of=ntfs.img bs=1000000 count=100
mkntfs --fast --force ntfs.img
mkdir -p mnt
valgrind ntfs-3g ntfs.img mnt -o debug &
sleep 1
echo -n > mnt/A
for i in `seq 1 7`; do
   ln mnt/A mnt/$i
done
cat mnt/A
fusermount -u mnt


(Note: I don't know exactly how permissions for 'ntfs-3g' works, but I was able to run valgrind on it as a normal user in a non-setuid installation with external FUSE.) The error message produced is:

Code:
==18279== Invalid read of size 8
==18279==    at 0x507B493: ntfs_attr_open (attrib.c:457)
==18279==    by 0x4043A2: ntfs_fuse_open (ntfs-3g.c:1157)
==18279==    by 0x4E402DF: fuse_fs_open (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E403F6: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E4A21B: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E4994A: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E4617B: fuse_session_loop (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E3E7C7: fuse_loop (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x408ED0: main (ntfs-3g.c:3913)
==18279==  Address 0x5b64cc8 is 8 bytes after a block of size 1,024 alloc'd
==18279==    at 0x4C2C04B: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18279==    by 0x50A23F0: ntfs_malloc (misc.c:57)
==18279==    by 0x50A1D23: ntfs_mft_record_alloc (mft.c:1704)
==18279==    by 0x5091154: __ntfs_create (dir.c:1508)
==18279==    by 0x5091D0B: ntfs_create (dir.c:1763)
==18279==    by 0x4052C7: ntfs_fuse_create (ntfs-3g.c:1712)
==18279==    by 0x40572F: ntfs_fuse_mknod_common (ntfs-3g.c:1848)
==18279==    by 0x4057CC: ntfs_fuse_create_file (ntfs-3g.c:1869)
==18279==    by 0x4E41E2C: fuse_fs_create (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E41F5F: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E4823C: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==    by 0x4E4994A: ??? (in /usr/lib/libfuse.so.2.9.3)
==18279==


Thu Aug 15, 2013 17:50
Profile
NTFS-3G Lead Developer

Joined: Tue Sep 04, 2007 17:22
Posts: 1286
Post Re: [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Hi,

Quote:
Furthermore, following that, the invalid memory access can be made by ntfs-3g during the same FUSE mount, without any external code using libntfs-3g (unlike what I posted before).

Yes, I could reproduce the condition, and there is a bug. Can you test the attached patch ?
Quote:
It appears to check for cases where the length of an attribute record overflows the MFT entry, but it only checks for 0 bytes of room before attempting to access the ATTR_RECORD at that location.

Yes, there should first be a test for four available bytes and check whether this is the end mark. If not the end, a second test for accessibility of length and check for length to not overflow. Will be fixed in next version to be more defensive against bad conditions.

Regards

Jean-Pierre


Attachments:
attrib.c.patch.gz [326 Bytes]
Downloaded 881 times
Thu Aug 15, 2013 22:28
Profile

Joined: Fri Aug 24, 2012 21:18
Posts: 30
Post Re: [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Code:
Yes, I could reproduce the condition, and there is a bug. Can you test the attached patch ?


Yes, the patch seemed to fix the invalid memory access. Just a thought though: there's a comment in layout.h that says data compression is only applied on non-resident attributes, so perhaps the block of code in the 'if' statement under consideration shouldn't even be entered unless the attribute is non-resident?


Fri Aug 16, 2013 01:54
Profile
NTFS-3G Lead Developer

Joined: Tue Sep 04, 2007 17:22
Posts: 1286
Post Re: [BUG] ntfs_attr_open() may read beyond end of MFT record buf
Hi,

Quote:
Just a thought though: there's a comment in layout.h that says data compression is only applied on non-resident attributes, so perhaps the block of code in the 'if' statement under consideration shouldn't even be entered unless the attribute is non-resident?

No, because this test also deals with files being recreated in a different compression mode, and when a file with a non-resident stream is truncated, it is not made resident.

Thank you for reporting the bug with details and testing the fix.

Regards

Jean-Pierre


Fri Aug 16, 2013 09:36
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Original forum style by Vjacheslav Trushkin.