]> err.no Git - util-linux/commitdiff
libblkid: fix non-magic FAT detection
authorKarel Zak <kzak@redhat.com>
Thu, 1 Oct 2009 13:14:48 +0000 (15:14 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 1 Oct 2009 13:21:26 +0000 (15:21 +0200)
On Wed, Sep 30, 2009 at 03:15:41PM +0200, Lawrence Rust wrote:
> The problem is with shlibs/blkid/src/probers/vfat.c.  At the end of
> this file  the struct blkid_idinfo is declared with some magic
> search strings.   In particular, 2 patterns are defined to match the
> single byte jmp/jxx opcodes at the start of a DOS boot sector.
> Because the partition was once formatted as a bootable DOS
> partition it matches these patterns and consequently the function
> probe_vfat is called.  For these simple pattern matches the function
> probe_fat_nomagic is called to filter out false positives.
>
> In normal circumstances only MSDOS 2 and earlier floppies should be
> detected by this function.  A very important feature of these disks
> is the boot signature - bytes 0x55, 0xaa at the end of the 1st
> sector which indicate to the BIOS that  the disk is bootable.  All
> MSDOS floppies have these bytes but the function probe_fat_nomagic
> doesn't check for them.

Note that the msdos/vfat superblock comments has been suggested by
Lawrence.

Reported-by: Lawrence Rust <lawrence@softsystem.co.uk>
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/superblocks/vfat.c

index 9c20ebd9af7694f55fbef6265c56c17ae9f33733..633e009e35cbf74cb8821e989744d83833740602 100644 (file)
@@ -46,7 +46,7 @@ struct vfat_super_block {
 /* 47*/        unsigned char   vs_label[11];
 /* 52*/        unsigned char   vs_magic[8];
 /* 5a*/        unsigned char   vs_dummy2[164];
-/*1fe*/        unsigned char   vs_pmagic[2];
+/* fe*/        unsigned char   vs_pmagic[2];
 };
 
 /* Yucky misaligned values */
@@ -58,19 +58,21 @@ struct msdos_super_block {
 /* 0e*/        uint16_t        ms_reserved;
 /* 10*/        uint8_t         ms_fats;
 /* 11*/        unsigned char   ms_dir_entries[2];
-/* 13*/        unsigned char   ms_sectors[2];
+/* 13*/        unsigned char   ms_sectors[2]; /* =0 iff V3 or later */
 /* 15*/        unsigned char   ms_media;
-/* 16*/        uint16_t        ms_fat_length;
+/* 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;
-/* 20*/        uint32_t        ms_total_sect;
-/* 24*/        unsigned char   ms_unknown[3];
+/* 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];
-/* 3d*/        unsigned char   ms_dummy2[192];
-/*1fe*/        unsigned char   ms_pmagic[2];
+/* 3e*/        unsigned char   ms_dummy2[192];
+/* fe*/        unsigned char   ms_pmagic[2];
 };
 
 struct vfat_dir_entry {
@@ -138,6 +140,15 @@ static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
 static int probe_fat_nomagic(blkid_probe pr, const struct blkid_idmag *mag)
 {
        struct msdos_super_block *ms;
+       unsigned char *buf;
+
+       buf = blkid_probe_get_sector(pr, 0);
+       if (!buf)
+               return -1;
+
+       /* Old floppies have a valid MBR signature */
+       if (buf[510] != 0x55 || buf[511] != 0xAA)
+               return 1;
 
        ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
        if (!ms)