]> err.no Git - util-linux/commitdiff
libblkid: add sanity checks for FAT to DOS PT parser
authorKarel Zak <kzak@redhat.com>
Wed, 20 Jan 2010 22:30:20 +0000 (23:30 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 16 Feb 2010 08:58:56 +0000 (09:58 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/Makefile.am
shlibs/blkid/src/fat.h [new file with mode: 0644]
shlibs/blkid/src/partitions/dos.c
shlibs/blkid/src/superblocks/vfat.c

index 90ce9bfc958a8d226b798b67a2cf8c8adbefe444..2d798b6a7f831c78714e30220778635e79da7fa3 100644 (file)
@@ -25,7 +25,7 @@ usrlib_exec_LTLIBRARIES = libblkid.la
 libblkid_la_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c  \
                     probe.c read.c resolve.c save.c tag.c version.c verify.c \
                     encode.c list.h blkidP.h superblocks/superblocks.h \
-                    config.c evaluate.c \
+                    config.c evaluate.c fat.h \
                     $(blkidinc_HEADERS) \
                     $(top_srcdir)/lib/blkdev.c \
                     $(top_srcdir)/lib/linux_version.c \
diff --git a/shlibs/blkid/src/fat.h b/shlibs/blkid/src/fat.h
new file mode 100644 (file)
index 0000000..b366464
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _BLKID_FAT_H
+#define _BLKID_FAT_H
+
+/* This FAT superblock is required for:
+ *
+ *     superblocks/vfat.c
+ *     partitions/dos.c
+ */
+
+/* Yucky misaligned values */
+struct vfat_super_block {
+/* 00*/        unsigned char   vs_ignored[3];
+/* 03*/        unsigned char   vs_sysid[8];
+/* 0b*/        unsigned char   vs_sector_size[2];
+/* 0d*/        uint8_t         vs_cluster_size;
+/* 0e*/        uint16_t        vs_reserved;
+/* 10*/        uint8_t         vs_fats;
+/* 11*/        unsigned char   vs_dir_entries[2];
+/* 13*/        unsigned char   vs_sectors[2];
+/* 15*/        unsigned char   vs_media;
+/* 16*/        uint16_t        vs_fat_length;
+/* 18*/        uint16_t        vs_secs_track;
+/* 1a*/        uint16_t        vs_heads;
+/* 1c*/        uint32_t        vs_hidden;
+/* 20*/        uint32_t        vs_total_sect;
+/* 24*/        uint32_t        vs_fat32_length;
+/* 28*/        uint16_t        vs_flags;
+/* 2a*/        uint8_t         vs_version[2];
+/* 2c*/        uint32_t        vs_root_cluster;
+/* 30*/        uint16_t        vs_fsinfo_sector;
+/* 32*/        uint16_t        vs_backup_boot;
+/* 34*/        uint16_t        vs_reserved2[6];
+/* 40*/        unsigned char   vs_unknown[3];
+/* 43*/        unsigned char   vs_serno[4];
+/* 47*/        unsigned char   vs_label[11];
+/* 52*/        unsigned char   vs_magic[8];
+/* 5a*/        unsigned char   vs_dummy2[0x1fe - 0x5a];
+/*1fe*/        unsigned char   vs_pmagic[2];
+} __attribute__((packed));
+
+/* Yucky misaligned values */
+struct msdos_super_block {
+/* 00*/        unsigned char   ms_ignored[3];
+/* 03*/        unsigned char   ms_sysid[8];
+/* 0b*/        unsigned char   ms_sector_size[2];
+/* 0d*/        uint8_t         ms_cluster_size;
+/* 0e*/        uint16_t        ms_reserved;
+/* 10*/        uint8_t         ms_fats;
+/* 11*/        unsigned char   ms_dir_entries[2];
+/* 13*/        unsigned char   ms_sectors[2]; /* =0 iff V3 or later */
+/* 15*/        unsigned char   ms_media;
+/* 16*/        uint16_t        ms_fat_length; /* Sectors per FAT */
+/* 18*/        uint16_t        ms_secs_track;
+/* 1a*/        uint16_t        ms_heads;
+/* 1c*/        uint32_t        ms_hidden;
+/* V3 BPB */
+/* 20*/        uint32_t        ms_total_sect; /* iff ms_sectors == 0 */
+/* V4 BPB */
+/* 24*/        unsigned char   ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */
+/* 27*/        unsigned char   ms_serno[4];
+/* 2b*/        unsigned char   ms_label[11];
+/* 36*/        unsigned char   ms_magic[8];
+/* 3e*/        unsigned char   ms_dummy2[0x1fe - 0x3e];
+/*1fe*/        unsigned char   ms_pmagic[2];
+} __attribute__((packed));
+
+
+static inline int blkid_fat_valid_media(struct msdos_super_block *ms)
+{
+       return 0xf8 <= ms->ms_media || ms->ms_media == 0xf0;
+}
+
+static inline int blkid_fat_valid_sectorsize(
+                       struct msdos_super_block *ms,
+                       uint16_t *sector_size)
+{
+       unsigned char *tmp = (unsigned char *) &ms->ms_sector_size;
+       uint16_t ssz;
+
+       ssz = tmp[0] + (tmp[1] << 8);
+
+       if (ssz != 0x200 && ssz != 0x400 && ssz != 0x800 && ssz != 0x1000)
+               return 0;
+       if (sector_size)
+               *sector_size = ssz;
+       return 1;
+}
+
+
+#endif /* _BLKID_FAT_H */
index 21728a5ae6622b301b8d688d5e300e25fbc25969..ec2ca1ebeeacdb2bcde462fee1485471ddd124db 100644 (file)
@@ -16,6 +16,7 @@
 #include "partitions.h"
 #include "dos.h"
 #include "aix.h"
+#include "fat.h"
 
 static const struct dos_subtypes {
        unsigned char type;
@@ -139,18 +140,30 @@ static int probe_dos_pt(blkid_probe pr, const struct blkid_idmag *mag)
        if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0)
                goto nothing;
 
-       p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
-
        /*
         * Now that the 55aa signature is present, this is probably
         * either the boot sector of a FAT filesystem or a DOS-type
-        * partition table. Reject this in case the boot indicator
-        * is not 0 or 0x80.
+        * partition table.
         */
-       for (p = p0, i = 0; i < 4; i++, p++) {
+       {
+               struct msdos_super_block *ms =
+                               (struct msdos_super_block *) data;
+
+               if (ms->ms_fats && ms->ms_reserved &&
+                   ms->ms_cluster_size &&
+                   blkid_fat_valid_media(ms) &&
+                   blkid_fat_valid_sectorsize(ms, NULL))
+                       goto nothing;           /* FAT */
+       }
+
+       p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET);
+
+       /*
+        * Reject PT where boot indicator is not 0 or 0x80.
+        */
+       for (p = p0, i = 0; i < 4; i++, p++)
                if (p->boot_ind != 0 && p->boot_ind != 0x80)
                        goto nothing;
-       }
 
        /*
         * GPT uses valid MBR
index 71c0fbcbd3500d5800f7652ffe8b18113b7261d9..b24f607513feb6af9e441940327e7a8c672a3588 100644 (file)
 
 #include "superblocks.h"
 
-/* Yucky misaligned values */
-struct vfat_super_block {
-/* 00*/        unsigned char   vs_ignored[3];
-/* 03*/        unsigned char   vs_sysid[8];
-/* 0b*/        unsigned char   vs_sector_size[2];
-/* 0d*/        uint8_t         vs_cluster_size;
-/* 0e*/        uint16_t        vs_reserved;
-/* 10*/        uint8_t         vs_fats;
-/* 11*/        unsigned char   vs_dir_entries[2];
-/* 13*/        unsigned char   vs_sectors[2];
-/* 15*/        unsigned char   vs_media;
-/* 16*/        uint16_t        vs_fat_length;
-/* 18*/        uint16_t        vs_secs_track;
-/* 1a*/        uint16_t        vs_heads;
-/* 1c*/        uint32_t        vs_hidden;
-/* 20*/        uint32_t        vs_total_sect;
-/* 24*/        uint32_t        vs_fat32_length;
-/* 28*/        uint16_t        vs_flags;
-/* 2a*/        uint8_t         vs_version[2];
-/* 2c*/        uint32_t        vs_root_cluster;
-/* 30*/        uint16_t        vs_fsinfo_sector;
-/* 32*/        uint16_t        vs_backup_boot;
-/* 34*/        uint16_t        vs_reserved2[6];
-/* 40*/        unsigned char   vs_unknown[3];
-/* 43*/        unsigned char   vs_serno[4];
-/* 47*/        unsigned char   vs_label[11];
-/* 52*/        unsigned char   vs_magic[8];
-/* 5a*/        unsigned char   vs_dummy2[0x1fe - 0x5a];
-/*1fe*/        unsigned char   vs_pmagic[2];
-} __attribute__((packed));
-
-/* Yucky misaligned values */
-struct msdos_super_block {
-/* 00*/        unsigned char   ms_ignored[3];
-/* 03*/        unsigned char   ms_sysid[8];
-/* 0b*/        unsigned char   ms_sector_size[2];
-/* 0d*/        uint8_t         ms_cluster_size;
-/* 0e*/        uint16_t        ms_reserved;
-/* 10*/        uint8_t         ms_fats;
-/* 11*/        unsigned char   ms_dir_entries[2];
-/* 13*/        unsigned char   ms_sectors[2]; /* =0 iff V3 or later */
-/* 15*/        unsigned char   ms_media;
-/* 16*/        uint16_t        ms_fat_length; /* Sectors per FAT */
-/* 18*/        uint16_t        ms_secs_track;
-/* 1a*/        uint16_t        ms_heads;
-/* 1c*/        uint32_t        ms_hidden;
-/* V3 BPB */
-/* 20*/        uint32_t        ms_total_sect; /* iff ms_sectors == 0 */
-/* V4 BPB */
-/* 24*/        unsigned char   ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */
-/* 27*/        unsigned char   ms_serno[4];
-/* 2b*/        unsigned char   ms_label[11];
-/* 36*/        unsigned char   ms_magic[8];
-/* 3e*/        unsigned char   ms_dummy2[0x1fe - 0x3e];
-/*1fe*/        unsigned char   ms_pmagic[2];
-} __attribute__((packed));
+/* {msdos,vfat}_super_block is defined in ../fat.h */
+#include "fat.h"
 
 struct vfat_dir_entry {
        uint8_t         name[11];
@@ -193,7 +139,7 @@ static int probe_fat_nomagic(blkid_probe pr, const struct blkid_idmag *mag)
                return 1;
 
        /* media check */
-       if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
+       if (!blkid_fat_valid_media(ms))
                return 1;
 
        /* fat counts(Linux kernel expects at least 1 FAT table) */
@@ -230,8 +176,6 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
        uint32_t buf_size, start_data_sect, next, root_start, root_dir_entries;
        const char *version = NULL;
 
-
-
        /* non-standard magic strings */
        if (mag->len <= 2 && probe_fat_nomagic(pr, mag) != 0)
                return 1;
@@ -245,10 +189,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
                return -1;
 
        /* sector size check */
-       tmp = (unsigned char *) &ms->ms_sector_size;
-       sector_size = tmp[0] + (tmp[1] << 8);
-       if (sector_size != 0x200 && sector_size != 0x400 &&
-           sector_size != 0x800 && sector_size != 0x1000)
+       if (!blkid_fat_valid_sectorsize(ms, &sector_size))
                return 1;
 
        tmp = (unsigned char *) &ms->ms_dir_entries;