File dosfstools-3.0.26-read-fat-overflow.patch of Package dosfstools.2621

From e8eff147e9da1185f9afd5b25948153a3b97cf52 Mon Sep 17 00:00:00 2001
From: Andreas Bombe <aeb@debian.org>
Date: Wed, 27 Apr 2016 21:38:37 +0200
Subject: [PATCH] read_boot(): Handle excessive FAT size specifications
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The variable used for storing the FAT size (in bytes) was an unsigned
int. Since the size in sectors read from the BPB was not sufficiently
checked, this could end up being zero after multiplying it with the
sector size while some offsets still stayed excessive. Ultimately it
would cause segfaults when accessing FAT entries for which no memory
was allocated.

Make it more robust by changing the types used to store FAT size to
off_t and abort if there is no room for data clusters. Additionally
check that FAT size is not specified as zero.

Fixes #25 and fixes #26.

Reported-by: Hanno Böck
Signed-off-by: Andreas Bombe <aeb@debian.org>
---
 src/boot.c     | 14 +++++++++++---
 src/fsck.fat.h |  2 +-
 2 files changed, 12 insertions(+), 4 deletions(-)

Index: dosfstools-3.0.26/src/boot.c
===================================================================
--- dosfstools-3.0.26.orig/src/boot.c
+++ dosfstools-3.0.26/src/boot.c
@@ -101,8 +101,8 @@ static void dump_boot(DOS_FS * fs, struc
 	   (unsigned long long)fs->fat_start,
 	   (unsigned long long)fs->fat_start / lss);
     printf("%10d FATs, %d bit entries\n", b->fats, fs->fat_bits);
-    printf("%10d bytes per FAT (= %u sectors)\n", fs->fat_size,
-	   fs->fat_size / lss);
+    printf("%10lld bytes per FAT (= %llu sectors)\n", (long long)fs->fat_size,
+	   (long long)fs->fat_size / lss);
     if (!fs->root_cluster) {
 	printf("Root directory starts at byte %llu (sector %llu)\n",
 	       (unsigned long long)fs->root_start,
@@ -326,7 +326,7 @@ void read_boot(DOS_FS * fs)
     struct boot_sector b;
     unsigned total_sectors;
     unsigned short logical_sector_size, sectors;
-    unsigned fat_length;
+    off_t fat_length;
     loff_t data_size;
 
     fs_read(0, sizeof(b), &b);
@@ -356,6 +356,8 @@ void read_boot(DOS_FS * fs)
 	    logical_sector_size);
     fat_length = le16toh(b.fat_length) ?
 	le16toh(b.fat_length) : le32toh(b.fat32_length);
+    if (!fat_length)
+        die("FAT size is zero.");
     fs->fat_start = (loff_t) le16toh(b.reserved) * logical_sector_size;
     fs->root_start = ((loff_t) le16toh(b.reserved) + b.fats * fat_length) *
 	logical_sector_size;
@@ -363,7 +365,11 @@ void read_boot(DOS_FS * fs)
     fs->data_start = fs->root_start + ROUND_TO_MULTIPLE(fs->root_entries <<
 							MSDOS_DIR_BITS,
 							logical_sector_size);
+
     data_size = (loff_t) total_sectors *logical_sector_size - fs->data_start;
+    if (data_size < fs->cluster_size)
+        die("Filesystem has no space for any data clusters");
+
     fs->clusters = data_size / fs->cluster_size;
     fs->root_cluster = 0;	/* indicates standard, pre-FAT32 root dir */
     fs->fsinfo_start = 0;	/* no FSINFO structure */
Index: dosfstools-3.0.26/src/fsck.fat.h
===================================================================
--- dosfstools-3.0.26.orig/src/fsck.fat.h
+++ dosfstools-3.0.26/src/fsck.fat.h
@@ -158,7 +158,7 @@ typedef struct {
 typedef struct {
     int nfats;
     loff_t fat_start;
-    unsigned int fat_size;	/* unit is bytes */
+    off_t fat_size;	/* unit is bytes */
     unsigned int fat_bits;	/* size of a FAT entry */
     unsigned int eff_fat_bits;	/* # of used bits in a FAT entry */
     uint32_t root_cluster;	/* 0 for old-style root dir */
openSUSE Build Service is sponsored by