From: John Lindgren Date: Wed, 11 May 2011 18:32:18 +0000 (-0400) Subject: blkid: don't read past end of FAT32 cluster chain X-Git-Tag: v2.20-rc1~276 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2e9096fe390b0815815f6f0b6abe2bc566aa85d;p=thirdparty%2Futil-linux.git blkid: don't read past end of FAT32 cluster chain When looking for a volume label on a FAT32 filesystem, blkid does not correctly handle special cluster values in the range 0x0FFFFFF8 to 0x0FFFFFFF, which mark the last cluster in a chain. As a result, it begins to read [what it treats as] FAT entries from past the end of the FAT. Depending on the data read, it may then try to parse random data from the filesystem (including user files, free space, and other directories) as though it were part of the root directory. Because parsing stops early when a volume label is found, the problem only occurs on filesystems without a volume label. When it occurs, it may result in a long sequence of lseek and read calls; on an older IDE drive with a 2 GB FAT32 partition, this amounted to around 3 seconds of disk I/O. After patching, blkid stop parsing as soon as it reaches a cluster value greater than or equal to the number of entries in the FAT. [kzak@redhat.com: - add le32_to_cpu()] Signed-off-by: John Lindgren --- diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c index 782bc143be..1584efae95 100644 --- a/shlibs/blkid/src/superblocks/vfat.c +++ b/shlibs/blkid/src/superblocks/vfat.c @@ -326,9 +326,11 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) /* Search the FAT32 root dir for the label attribute */ uint32_t buf_size = vs->vs_cluster_size * sector_size; uint32_t start_data_sect = reserved + fat_size; + uint32_t entries = le32_to_cpu(vs->vs_fat32_length) * + sector_size / sizeof(uint32_t); uint32_t next = le32_to_cpu(vs->vs_root_cluster); - while (next && --maxloop) { + while (next && next < entries && --maxloop) { uint32_t next_sect_off; uint64_t next_off, fat_entry_off; int count;