]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: Fix out of bounds reads on bad NTFS Master File Table
authorAlden Tondettar <alden.tondettar@gmail.com>
Tue, 24 Jan 2017 06:27:59 +0000 (23:27 -0700)
committerKarel Zak <kzak@redhat.com>
Wed, 25 Jan 2017 10:39:10 +0000 (11:39 +0100)
The NTFS prober does not validate certain fields in struct file_attribute,
and could attempt to read the disk label from outside the space allocated
for the Master File Table.  Perform the appropriate checks.

Note that one variable (attr_off) is now 64-bit, so a check for integer
overflow has been removed as unneeded/confusing.

Signed-off-by: Alden Tondettar <alden.tondettar@gmail.com>
libblkid/src/superblocks/ntfs.c

index 751581164170b6b494ca72ec6bd5fb2b358b0423..3a9d5cb017639211381a3968d61bd8f2af029c44 100644 (file)
@@ -84,9 +84,9 @@ static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
        struct ntfs_super_block *ns;
        struct master_file_table_record *mft;
 
-       uint32_t sectors_per_cluster, mft_record_size, attr_off;
+       uint32_t sectors_per_cluster, mft_record_size;
        uint16_t sector_size;
-       uint64_t nr_clusters, off;
+       uint64_t nr_clusters, off, attr_off;
        unsigned char *buf_mft;
 
        ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
@@ -175,7 +175,7 @@ static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
        mft = (struct master_file_table_record *) buf_mft;
        attr_off = le16_to_cpu(mft->attrs_offset);
 
-       while (attr_off < mft_record_size &&
+       while (attr_off + sizeof(struct file_attribute) <= mft_record_size &&
               attr_off <= le32_to_cpu(mft->bytes_allocated)) {
 
                uint32_t attr_len;
@@ -193,12 +193,12 @@ static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
                        unsigned int val_len = le32_to_cpu(attr->value_len);
                        unsigned char *val = ((uint8_t *) attr) + val_off;
 
-                       blkid_probe_set_utf8label(pr, val, val_len, BLKID_ENC_UTF16LE);
+                       if (attr_off + val_off + val_len <= mft_record_size)
+                               blkid_probe_set_utf8label(pr, val, val_len,
+                                                         BLKID_ENC_UTF16LE);
                        break;
                }
 
-               if (UINT_MAX - attr_len < attr_off)
-                       break;
                attr_off += attr_len;
        }