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