When setting a security descriptor on an NTFS v1.2 format file in an
NTFS v3.0+ volume, NTFS-3G would migrate $STANDARD_INFORMATION to the
new format, which requires extending its size from 48 to 72 bytes.  If
this happened while the file's MFT record was almost full, and none of
the file's attributes could be made non-resident, and the file did not
have an attribute list attribute, then the operation would unexpectedly
fail with ENOENT.  Fix this by adding an attribute list to the file in
this situation.

Note that this bug would have been very difficult to hit under normal
usage because it required the MFT record to be filled to just the right
amount with attributes that cannot be made nonresident, such as
$FILE_NAME attributes.  The $SECURITY_DESCRIPTOR attribute must also
have already been made nonresident, since otherwise space could be freed
by making it nonresident.  Nevertheless, here's a script which
reproduces the bug:

        fallocate -l 100M ntfs.img
        mkntfs --fast --force ntfs.img
        mkdir -p mnt
        ntfs-3g ntfs.img mnt
        touch mnt/file
        ln mnt/file mnt/00000000000000000000000000000001
        ln mnt/file mnt/00000000000000000000000000000002
        ln mnt/file mnt/00000000000000000000000000000003
        ln mnt/file mnt/0000000000000000000000000000004
        setfattr mnt/file -n system.ntfs_object_id -v 
0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
        setfattr mnt/file -n system.ntfs_acl -v 
0x0100048014000000240000000000000034000000010200000000000520000000200200000102000000000005200000002002000002001c000100000000031400ff011f00010100000000000100000000

The hard links make the MFT record of "mnt/file" nearly full.  Then,
assigning an object ID forces $SECURITY_DESCRIPTOR to be nonresident in
favor of $OBJECT_ID, while still keeping the MFT record nearly full.
Finally, the last command, which sets the file's security descriptor,
should succeed; but in fact it failed with "No such file or directory".

This bug was found using the wlfuzz program from wimlib.

Signed-off-by: Eric Biggers <ebigge...@gmail.com>
---
 libntfs-3g/attrib.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c
index a5a6549a..1cc3ef64 100644
--- a/libntfs-3g/attrib.c
+++ b/libntfs-3g/attrib.c
@@ -5142,6 +5142,10 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, 
const s64 newsize,
         */
        if (na->type==AT_STANDARD_INFORMATION || na->type==AT_ATTRIBUTE_LIST) {
                ntfs_attr_put_search_ctx(ctx);
+               if (!NInoAttrList(na->ni) && ntfs_inode_add_attrlist(na->ni)) {
+                       ntfs_log_perror("Could not add attribute list");
+                       return -1;
+               }
                if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
                                non_resident_end) + 8)) {
                        ntfs_log_perror("Could not free space in MFT record");
-- 
2.11.0


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
ntfs-3g-devel mailing list
ntfs-3g-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ntfs-3g-devel

Reply via email to