]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: (exfat): validate fields used by prober
authorThomas Weißschuh <thomas@t-8ch.de>
Thu, 3 Oct 2024 07:14:57 +0000 (09:14 +0200)
committerThomas Weißschuh <thomas@t-8ch.de>
Thu, 3 Oct 2024 07:17:00 +0000 (09:17 +0200)
The exFAT specification lists valid value ranges for the superblock
fields. Validate the fields interpreted by the libblkid prober to avoid
undefined behaviour.

Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
libblkid/src/superblocks/exfat.c
tests/ts/fuzzers/test_blkid_fuzz_files/oss-fuzz-371061095 [new file with mode: 0644]

index 18a3e07c7a2a5f74a4b8e8aebb9c6d0b9ee1c098..a7d3e02980f219d38ed8b1f67a12775af705afbb 100644 (file)
@@ -161,6 +161,8 @@ static int exfat_validate_checksum(blkid_probe pr,
        return 1;
 }
 
+#define in_range_inclusive(val, start, stop) (val >= start && val <= stop)
+
 static int exfat_valid_superblock(blkid_probe pr, const struct exfat_super_block *sb)
 {
        if (le16_to_cpu(sb->BootSignature) != 0xAA55)
@@ -172,10 +174,41 @@ static int exfat_valid_superblock(blkid_probe pr, const struct exfat_super_block
        if (memcmp(sb->JumpBoot, "\xEB\x76\x90", 3) != 0)
                return 0;
 
+       if (memcmp(sb->FileSystemName, "EXFAT   ", 8) != 0)
+               return 0;
+
        for (size_t i = 0; i < sizeof(sb->MustBeZero); i++)
                if (sb->MustBeZero[i] != 0x00)
                        return 0;
 
+       if (!in_range_inclusive(sb->NumberOfFats, 1, 2))
+               return 0;
+
+       if (!in_range_inclusive(sb->BytesPerSectorShift, 9, 12))
+               return 0;
+
+       if (!in_range_inclusive(sb->SectorsPerClusterShift,
+                               0,
+                               25 - sb->BytesPerSectorShift))
+               return 0;
+
+       if (!in_range_inclusive(le32_to_cpu(sb->FatOffset),
+                               24,
+                               le32_to_cpu(sb->ClusterHeapOffset) -
+                                       (le32_to_cpu(sb->FatLength) * sb->NumberOfFats)))
+               return 0;
+
+       if (!in_range_inclusive(le32_to_cpu(sb->ClusterHeapOffset),
+                               le32_to_cpu(sb->FatOffset) +
+                                       le32_to_cpu(sb->FatLength) * sb->NumberOfFats,
+                               1U << (32 - 1)))
+               return 0;
+
+       if (!in_range_inclusive(le32_to_cpu(sb->FirstClusterOfRootDirectory),
+                               2,
+                               le32_to_cpu(sb->ClusterCount) + 1))
+               return 0;
+
        if (!exfat_validate_checksum(pr, sb))
                return 0;
 
diff --git a/tests/ts/fuzzers/test_blkid_fuzz_files/oss-fuzz-371061095 b/tests/ts/fuzzers/test_blkid_fuzz_files/oss-fuzz-371061095
new file mode 100644 (file)
index 0000000..c16597d
Binary files /dev/null and b/tests/ts/fuzzers/test_blkid_fuzz_files/oss-fuzz-371061095 differ