]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: improve MBR vs. FAT + boot sector detection
authorKarel Zak <kzak@redhat.com>
Tue, 27 Jan 2015 11:58:19 +0000 (12:58 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 27 Jan 2015 12:09:27 +0000 (13:09 +0100)
It seems that some systems are able to produce boot sector + MBR with
almost valid FAT superblock. The libblkid already checks for FAT magic
string, media, correct sector and dir size, etc. -- but all this is
not enough.

The patch add to FAT prober also MBR detection to make sure that there
is no MBR with usable first partition. All this is enabled for
whole-disk devices only.

first sector (and this is no FAT baby ;-)

$ hexdump -C -n 512 /dev/nbd0
00000000  eb 58 90 4d 53 44 4f 53  35 2e 30 00 02 10 16 10  |.X.MSDOS5.0.....|
00000010  02 00 00 00 00 f8 00 00  3f 00 ff 00 00 00 00 00  |........?.......|
00000020  00 00 40 01 f5 27 00 00  00 00 00 00 02 00 00 00  |..@..'..........|
00000030  01 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  80 01 29 c5 a3 06 1a 4e  4f 20 4e 41 4d 45 20 20  |..)....NO NAME  |
00000050  20 20 46 41 54 33 32 20  20 20 33 c9 8e d1 bc f4  |  FAT32   3.....|
00000060  7b 8e c1 8e d9 bd 00 7c  88 56 40 88 4e 02 8a 56  |{......|.V@.N..V|
00000070  40 b4 41 bb aa 55 cd 13  72 10 81 fb 55 aa 75 0a  |@.A..U..r...U.u.|
00000080  f6 c1 01 74 05 fe 46 02  eb 2d 8a 56 40 b4 08 cd  |...t..F..-.V@...|
00000090  13 73 05 b9 ff ff 8a f1  66 0f b6 c6 40 66 0f b6  |.s......f...@f..|
000000a0  d1 80 e2 3f f7 e2 86 cd  c0 ed 06 41 66 0f b7 c9  |...?.......Af...|
000000b0  66 f7 e1 66 89 46 f8 83  7e 16 00 75 39 83 7e 2a  |f..f.F..~..u9.~*|
000000c0  00 77 33 66 8b 46 1c 66  83 c0 0c bb 00 80 b9 01  |.w3f.F.f........|
000000d0  00 e8 2c 00 e9 a8 03 a1  f8 7d 80 c4 7c 8b f0 ac  |..,......}..|...|
000000e0  84 c0 74 17 3c ff 74 09  b4 0e bb 07 00 cd 10 eb  |..t.<.t.........|
000000f0  ee a1 fa 7d eb e4 a1 7d  80 eb df 98 cd 16 cd 19  |...}...}........|
00000100  66 60 80 7e 02 00 0f 84  20 00 66 6a 00 66 50 06  |f`.~.... .fj.fP.|
00000110  53 66 68 10 00 01 00 b4  42 8a 56 40 8b f4 cd 13  |Sfh.....B.V@....|
00000120  66 58 66 58 66 58 66 58  eb 33 66 3b 46 f8 72 03  |fXfXfXfX.3f;F.r.|
00000130  f9 eb 2a 66 33 d2 66 0f  b7 4e 18 66 f7 f1 fe c2  |..*f3.f..N.f....|
00000140  8a ca 66 8b d0 66 c1 ea  10 f7 76 1a 86 d6 8a 56  |..f..f....v....V|
00000150  40 8a e8 c0 e4 06 0a cc  b8 01 02 cd 13 66 61 0f  |@............fa.|
00000160  82 74 ff 81 c3 00 02 66  40 49 75 94 c3 42 4f 4f  |.t.....f@Iu..BOO|
00000170  54 4d 47 52 20 20 20 20  00 00 00 00 00 00 00 00  |TMGR    ........|
00000180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001a0  00 00 00 00 00 00 00 00  00 00 00 00 0d 0a 44 69  |..............Di|
000001b0  73 6b 20 65 72 72 6f 72  ff 0d 0a 50 72 65 00 00  |sk error...Pre..|
000001c0  01 01 0c 3f e0 ff 00 08  00 00 00 f8 3f 01 00 00  |...?........?...|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|

MBR:
$ hexdump -C -s 446 -n $((512 - 446)) /dev/nbd0
000001be  00 00 01 01 0c 3f e0 ff  00 08 00 00 00 f8 3f 01  |.....?........?.|
000001ce  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001fe  55 aa                                             |U.|

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1182831
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/partitions/dos.c
libblkid/src/superblocks/vfat.c

index 25399080020a4d47fd969bd3edecaf1e7f7b9d4e..44e49dc3df9f845df16737a6639b2a0b3761fec4 100644 (file)
@@ -153,16 +153,6 @@ static int probe_dos_pt(blkid_probe pr,
        if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0)
                goto nothing;
 
-       /*
-        * Now that the 55aa signature is present, this is probably
-        * either the boot sector of a FAT filesystem or a DOS-type
-        * partition table.
-        */
-       if (blkid_probe_is_vfat(pr) == 1) {
-               DBG(LOWPROBE, ul_debug("probably FAT -- ignore"));
-               goto nothing;
-       }
-
        p0 = mbr_get_partition(data, 0);
 
        /*
@@ -184,6 +174,16 @@ static int probe_dos_pt(blkid_probe pr,
                }
        }
 
+       /*
+        * Now that the 55aa signature is present, this is probably
+        * either the boot sector of a FAT filesystem or a DOS-type
+        * partition table.
+        */
+       if (blkid_probe_is_vfat(pr) == 1) {
+               DBG(LOWPROBE, ul_debug("probably FAT -- ignore"));
+               goto nothing;
+       }
+
        blkid_probe_use_wiper(pr, MBR_PT_OFFSET, 512 - MBR_PT_OFFSET);
 
        id = mbr_get_id(data);
index f38deac8b24c4578eef3a15784156b4311258f18..00df4cb7dc5e9daad5edeb021908f4590cf5da76 100644 (file)
@@ -16,6 +16,7 @@
 #include <ctype.h>
 #include <stdint.h>
 
+#include "pt-mbr.h"
 #include "superblocks.h"
 
 /* Yucky misaligned values */
@@ -169,7 +170,8 @@ static unsigned char *search_fat_label(blkid_probe pr,
        return NULL;
 }
 
-static int fat_valid_superblock(const struct blkid_idmag *mag,
+static int fat_valid_superblock(blkid_probe pr,
+                       const struct blkid_idmag *mag,
                        struct msdos_super_block *ms,
                        struct vfat_super_block *vs,
                        uint32_t *cluster_count, uint32_t *fat_size)
@@ -243,6 +245,20 @@ static int fat_valid_superblock(const struct blkid_idmag *mag,
        if (cluster_count)
                *cluster_count = __cluster_count;
 
+       if (blkid_probe_is_wholedisk(pr)) {
+               /* OK, seems like FAT, but it's possible that we found boot
+                * sector with crazy FAT-like stuff (magic strings, media,
+                * etc..) before MBR. Let's make sure that there is no MBR with
+                * usable partition. */
+               unsigned char *buf = (unsigned char *) ms;
+               if (mbr_is_valid_magic(buf)) {
+                       struct dos_partition *p0 = mbr_get_partition(buf, 0);
+                       if (dos_partition_get_size(p0) != 0 &&
+                           (p0->boot_ind == 0 || p0->boot_ind == 0x80))
+                               return 0;
+               }
+       }
+
        return 1;       /* valid */
 }
 
@@ -270,7 +286,7 @@ int blkid_probe_is_vfat(blkid_probe pr)
        if (!vs)
                return errno ? -errno : 0;
 
-       return fat_valid_superblock(mag, ms, vs, NULL, NULL);
+       return fat_valid_superblock(pr, mag, ms, vs, NULL, NULL);
 }
 
 /* FAT label extraction from the root directory taken from Kay
@@ -293,7 +309,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
        if (!vs)
                return errno ? -errno : 1;
 
-       if (!fat_valid_superblock(mag, ms, vs, &cluster_count, &fat_size))
+       if (!fat_valid_superblock(pr, mag, ms, vs, &cluster_count, &fat_size))
                return 1;
 
        sector_size = unaligned_le16(&ms->ms_sector_size);