From 4016e5fd396b780a7cac7d4756c650df778cb251 Mon Sep 17 00:00:00 2001 From: Sven Hoexter Date: Thu, 5 Nov 2015 20:06:20 +0100 Subject: [PATCH] Add d/patches/check-sector-and-cluster-size. Fix for https://github.com/relan/exfat/issues/5 found and reported by The Fuzzing Project. Add d/patches/detect-infinite-loop. Fix for https://github.com/relan/exfat/issues/6 found and reported by The Fuzzing Project. --- debian/changelog | 11 +++++ debian/patches/check-sector-and-cluster-size | 49 ++++++++++++++++++++ debian/patches/detect-infinite-loop | 48 +++++++++++++++++++ debian/patches/series | 2 + 4 files changed, 110 insertions(+) create mode 100644 debian/patches/check-sector-and-cluster-size create mode 100644 debian/patches/detect-infinite-loop diff --git a/debian/changelog b/debian/changelog index 5be252c..0f7ae6e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +fuse-exfat (0.9.7-2+deb7u1) UNRELEASED; urgency=medium + + * Add d/patches/check-sector-and-cluster-size. Fix for + https://github.com/relan/exfat/issues/5 found and reported by + The Fuzzing Project. + * Add d/patches/detect-infinite-loop. Fix for + https://github.com/relan/exfat/issues/6 found and reported by + The Fuzzing Project. + + -- + fuse-exfat (0.9.7-2) unstable; urgency=low * Switch from dh compat level 8 to 9. diff --git a/debian/patches/check-sector-and-cluster-size b/debian/patches/check-sector-and-cluster-size new file mode 100644 index 0000000..c630c2d --- /dev/null +++ b/debian/patches/check-sector-and-cluster-size @@ -0,0 +1,49 @@ +Patch for https://github.com/relan/exfat/issues/5 +See also: +https://blog.fuzzing-project.org/25-Heap-overflow-and-endless-loop-in-exfatfsck-exfat-utils.html +Index: exfat-utils/libexfat/mount.c +=================================================================== +--- exfat-utils.orig/libexfat/mount.c ++++ exfat-utils/libexfat/mount.c +@@ -172,6 +172,24 @@ int exfat_mount(struct exfat* ef, const + exfat_error("exFAT file system is not found"); + return -EIO; + } ++ /* sector cannot be smaller than 512 bytes */ ++ if (ef->sb->sector_bits < 9) ++ { ++ exfat_close(ef->dev); ++ exfat_error("too small sector size: 2^%hhd", ef->sb->sector_bits); ++ free(ef->sb); ++ return -EIO; ++ } ++ /* officially exFAT supports cluster size up to 32 MB */ ++ if ((int) ef->sb->sector_bits + (int) ef->sb->spc_bits > 25) ++ { ++ exfat_close(ef->dev); ++ exfat_error("too big cluster size: 2^(%hhd+%hhd)", ++ ef->sb->sector_bits, ef->sb->spc_bits); ++ free(ef->sb); ++ return -EIO; ++ } ++ + if (ef->sb->version.major != 1 || ef->sb->version.minor != 0) + { + exfat_close(ef->dev); +@@ -187,16 +205,6 @@ int exfat_mount(struct exfat* ef, const + exfat_error("unsupported FAT count: %hhu", ef->sb->fat_count); + return -EIO; + } +- /* officially exFAT supports cluster size up to 32 MB */ +- if ((int) ef->sb->sector_bits + (int) ef->sb->spc_bits > 25) +- { +- exfat_close(ef->dev); +- free(ef->sb); +- exfat_error("too big cluster size: 2^%d", +- (int) ef->sb->sector_bits + (int) ef->sb->spc_bits); +- return -EIO; +- } +- + ef->zero_cluster = malloc(CLUSTER_SIZE(*ef->sb)); + if (ef->zero_cluster == NULL) + { diff --git a/debian/patches/detect-infinite-loop b/debian/patches/detect-infinite-loop new file mode 100644 index 0000000..94f6bbc --- /dev/null +++ b/debian/patches/detect-infinite-loop @@ -0,0 +1,48 @@ +Patch for https://github.com/relan/exfat/issues/6 +See also: +https://blog.fuzzing-project.org/25-Heap-overflow-and-endless-loop-in-exfatfsck-exfat-utils.html +Index: exfat-utils/libexfat/mount.c +=================================================================== +--- exfat-utils.orig/libexfat/mount.c ++++ exfat-utils/libexfat/mount.c +@@ -27,17 +27,32 @@ + + static uint64_t rootdir_size(const struct exfat* ef) + { +- uint64_t clusters = 0; ++ uint32_t clusters = 0; ++ uint32_t clusters_max = le32_to_cpu(ef->sb->cluster_count); + cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster); + +- while (!CLUSTER_INVALID(rootdir_cluster)) +- { +- clusters++; +- /* root directory cannot be contiguous because there is no flag +- to indicate this */ +- rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster); ++ /* Iterate all clusters of the root directory to calculate its size. ++ It can't be contiguous because there is no flag to indicate this. */ ++ do ++ { ++ if (clusters == clusters_max) /* infinite loop detected */ ++ { ++ exfat_error("root directory cannot occupy all %d clusters", ++ clusters); ++ return 0; ++ } ++ if (CLUSTER_INVALID(rootdir_cluster)) ++ { ++ exfat_error("bad cluster %#x while reading root directory", ++ rootdir_cluster); ++ return 0; ++ } ++ rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster); ++ clusters++; + } +- return clusters * CLUSTER_SIZE(*ef->sb); ++ while (rootdir_cluster != EXFAT_CLUSTER_END); ++ ++ return (uint64_t) clusters * CLUSTER_SIZE(*ef->sb); + } + + static const char* get_option(const char* options, const char* option_name) diff --git a/debian/patches/series b/debian/patches/series index e3ec1be..de54dee 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,2 +1,4 @@ honor-cppflags utf16-fix +check-sector-and-cluster-size +detect-infinite-loop -- 2.39.5