summaryrefslogtreecommitdiffstats
path: root/shlibs/blkid/src
diff options
context:
space:
mode:
authorKarel Zak2010-01-20 23:30:20 +0100
committerKarel Zak2010-01-21 00:20:19 +0100
commit2b09166ddac2cd671ca28111a25e342304d6223f (patch)
tree79c5288ceb5b2a9707305eb750e0e534c5b54661 /shlibs/blkid/src
parentblkid: probe for PT, don't probe for FS on small whole-disks (diff)
downloadkernel-qcow2-util-linux-2b09166ddac2cd671ca28111a25e342304d6223f.tar.gz
kernel-qcow2-util-linux-2b09166ddac2cd671ca28111a25e342304d6223f.tar.xz
kernel-qcow2-util-linux-2b09166ddac2cd671ca28111a25e342304d6223f.zip
libblkid: add sanity checks for FAT to DOS PT parser
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs/blkid/src')
-rw-r--r--shlibs/blkid/src/Makefile.am2
-rw-r--r--shlibs/blkid/src/fat.h90
-rw-r--r--shlibs/blkid/src/partitions/dos.c25
-rw-r--r--shlibs/blkid/src/superblocks/vfat.c67
4 files changed, 114 insertions, 70 deletions
diff --git a/shlibs/blkid/src/Makefile.am b/shlibs/blkid/src/Makefile.am
index 90ce9bfc9..2d798b6a7 100644
--- a/shlibs/blkid/src/Makefile.am
+++ b/shlibs/blkid/src/Makefile.am
@@ -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
index 000000000..b3664641c
--- /dev/null
+++ b/shlibs/blkid/src/fat.h
@@ -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 */
diff --git a/shlibs/blkid/src/partitions/dos.c b/shlibs/blkid/src/partitions/dos.c
index 21728a5ae..ec2ca1ebe 100644
--- a/shlibs/blkid/src/partitions/dos.c
+++ b/shlibs/blkid/src/partitions/dos.c
@@ -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
diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c
index 71c0fbcbd..b24f60751 100644
--- a/shlibs/blkid/src/superblocks/vfat.c
+++ b/shlibs/blkid/src/superblocks/vfat.c
@@ -18,62 +18,8 @@
#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;