When copying an attribute name which contains a null, it is truncated
and this may lead to accessing non-allocated bytes when relying on the
expected name length. Such (illegal) names must therefore be rejected.
Before reading a full attribute value for internal use, its expected
length has been checked to be < 0x40000. However the allocated size
in the runlist may be much bigger as a consequence of a bug or malice.
To prevent malloc'ing excessive size, restrict the size of the last
run to read to the needed length.
When copying an attribute name which contains a null, it is truncated
and this may lead to accessing non-allocated bytes when relying on the
expected name length. Such names must therefore be rejected.
The recent detection of a truncated attribute list entry overlooked the
normal detection of the end of list. Moreover the check for name
overflow is to be done later and not needed at this stage.
Allocating clusters to the main bitmap may imply updating the bitmap
itself within a cluster not yet allocated. This can turn into endless
recursions and has to be rejected. Currently the bitmap is assumed
to be fully allocated.
Checked that attributes are [non-]resident when they have to be, and
grouped consistency checks on each of them in a dedicated function.
Consequenly request the checks where needed and remove existing index
checks.
The end of the attributes must be checked against the space in use
rather than the allocated space. This contributes to the safety of
subsequent attribute resizing.
Make sure the attribute designated to readall() has a reasonable size.
Apart from a bitmap, in a valid call, the attribute size is limited to
65536, and bitmaps are limited by the number of cluster.
Make sure the attributes fully lie within the MFT record, and make sure
their variable components (name, runlist, value) fully lie within the
attribute.
When filling a hole in a sparse file, the beginning of the runlist
does not need to be updated. However the allocated size is within
the extent holding its beginning and it needs to be updated.
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.
(contributed by Eric Biggers)
For 64-bit (e.g. x86_64) Linux the 64-bit wide types resolve to long,
not long long as is the case in 32-bit (e.g. i386) Linux. So we need an
explicit cast to long long for 64-bit types since the format string must
specify the 'll' modifier in order to print 64-bit values.
This commit addresses issues where little-endian variables are emitted
raw to a log or output stream which is to be interpreted by the user.
Outputting data in non-native endianness can cause confusion for anybody
attempting to debug issues with a file system.
When writing to compressed data, the function ntfs_attr_pwrite()
cannot cross a compression block border. This is a problem for archivers
which rely on libntfs-3g, so the function is now wrapped in another one
which restarts the writing as needed.
chkdsk deletes the ACLs when they are bad or when they are not used any
more. This fixes inserting a new ACL after the previously last ACL (or
even all of them) was deleted.
A bug was introduced by commit d2c7d40a2b :
when the beginning of a file was a hole and the runlist span over several
MFT extents, the runlist was not mapped on filling the initial hole.
This lead to a crash when using torrent to download big files.
When the runlist of the data attribute of MFT has to be split across
several extents, the location of each extent has to be known from the
runlist present in previous extents. So, force the first extent into
record 15 to avoid a bad layout.
When a hole in a sparse file was filled, the runlist was fully recomputed.
When a sparse file spans over several MFT extents, this patch leads to
only recompute the runlist from the modified extent to the end.
Updating an attribute may imply decompressing runlists which are not
contiguous, leaving an unmapped region between them. When checking whether
the attribute has been made sparse, such unmapped regions should be ignored
This mostly happens after updating an index. (fix by Forrest Liu)
When calling ntfstruncate() to expand a resident attribute, the function
is called again recursively, losing the requirement for not inserting
holes. This is for forwarding the requirement (used by ntfscp).
When testing whether a stream has been wiped out for possibly changing
its compression status, only the non-resident case was considered.
This fixes the test for streams which were never made non-resident.
- Replaced 'ntfschar*' parameters with 'const ntfschar*' where
appropriate (the function does not need to modify the string).
- Replaced some instances of 'u8*' and 'char*' read-only buffer
arguments with 'const u8*' and 'const char*'.
Appending data to a file is done in two steps : first extending the
file to the required size, then inserting data in the created space.
There is no need to recompute the runlist at the end of the first
step, just be sure the original configuration is rolled back if inserting
data leads to an error.
When computing the runlist for the first non-resident write to an
attribute, an inconsistency was created between the attribute image
and the ntfs_attr structure, which could cause an MFT record overflow
when the first write is huge and fragmented (reported by Vito Caputo).
Logging of fixup errors for uninitialized inodes cause unnecessary
worries and suspicion of malfunctions in ntfs-3g. This patch silences
these loggings in ntfsclone and ntfsresize which have to analyze all
inodes, including the uninitialized ones.
When clearing a volume name in Windows, $VOLUME_NAME is set to size 0, even if
the standard $AttrDef says that the minimum size is 2.
So the definition in $AttrDef doesn't reflect actual Windows behaviour in this
particular case, and to clear volume names ourselves the way Windows does it,
we must must add a special rule to permit us to truncate the $VOLUME_NAME
attribute to 0 even when $AttrDef specifies a higher value as minimum size.
When an attribute is truncated and made resident, the NAttrFullyMapped
flags has to be cleared, otherwise the attribute cannot be properly
mapped when the attribute is later made non-resident again.