From 60717a846deaaea47e50ce58872869f7bd1103b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Tue, 21 Sep 2021 10:56:06 +0200 Subject: [PATCH] Avoided allocating and reading an attribute beyond its full size 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. --- libntfs-3g/attrib.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c index 00bfca84..51c8536f 100644 --- a/libntfs-3g/attrib.c +++ b/libntfs-3g/attrib.c @@ -216,6 +216,7 @@ s64 ntfs_get_attribute_value(const ntfs_volume *vol, if (total + (rl[i].length << vol->cluster_size_bits) >= sle64_to_cpu(a->data_size)) { unsigned char *intbuf = NULL; + s64 intlth; /* * We have reached the last run so we were going to * overflow when executing the ntfs_pread() which is @@ -229,8 +230,18 @@ s64 ntfs_get_attribute_value(const ntfs_volume *vol, * We have reached the end of data size so we were * going to overflow in the same fashion. * Temporary fix: same as above. + * + * For safety, limit the amount to read to the + * needed size, knowing that the whole attribute + * size has been checked to be <= 0x40000. */ - intbuf = ntfs_malloc(rl[i].length << vol->cluster_size_bits); + intlth = (sle64_to_cpu(a->data_size) - total + + vol->cluster_size - 1) + >> vol->cluster_size_bits; + if (rl[i].length < intlth) + intlth = rl[i].length; + intbuf = (u8*)ntfs_malloc(intlth + << vol->cluster_size_bits); if (!intbuf) { free(rl); return 0; @@ -246,14 +257,15 @@ s64 ntfs_get_attribute_value(const ntfs_volume *vol, * - Yes we can, in sparse files! But not necessarily * size of 16, just run length. */ - r = ntfs_pread(vol->dev, rl[i].lcn << - vol->cluster_size_bits, rl[i].length << - vol->cluster_size_bits, intbuf); - if (r != rl[i].length << vol->cluster_size_bits) { + r = ntfs_pread(vol->dev, + rl[i].lcn << vol->cluster_size_bits, + intlth << vol->cluster_size_bits, + intbuf); + if (r != intlth << vol->cluster_size_bits) { #define ESTR "Error reading attribute value" if (r == -1) ntfs_log_perror(ESTR); - else if (r < rl[i].length << + else if (r < intlth << vol->cluster_size_bits) { ntfs_log_debug(ESTR ": Ran out of input data.\n"); errno = EIO;