diff options
author | marcel <marcel@FreeBSD.org> | 2008-02-28 22:30:41 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2008-02-28 22:30:41 +0000 |
commit | aa08e756e25b6a8d5d4eaaf6def143fdb69f758a (patch) | |
tree | 6f6e295a4fe6a03d9e080d77f59e03181bd1500a | |
parent | c1cd98f4218d53ac138627299e2b59d0dfc43c07 (diff) | |
download | FreeBSD-src-aa08e756e25b6a8d5d4eaaf6def143fdb69f758a.zip FreeBSD-src-aa08e756e25b6a8d5d4eaaf6def143fdb69f758a.tar.gz |
Better handle false positives. The MBR differs from the boot sector
only because there's a partition table where the boot sector has
boot code. Boot sectors without boot code look like a MBR for all
practical purposes. This change adds a check for the partition table
and fails the probe when it's obvously invalid. The assumption being
that the sector contains a boot sector and not a MBR.
More checks are needed to distinguish a boot secto without boot code
from a (empty) MBR.
-rw-r--r-- | sys/geom/part/g_part_mbr.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c index b096b33..9e6b56e 100644 --- a/sys/geom/part/g_part_mbr.c +++ b/sys/geom/part/g_part_mbr.c @@ -252,22 +252,42 @@ static int g_part_mbr_probe(struct g_part_table *table, struct g_consumer *cp) { struct g_provider *pp; - u_char *buf; - int error, res; + u_char *buf, *p; + int error, index, res; + uint16_t magic; pp = cp->provider; /* Sanity-check the provider. */ if (pp->sectorsize < MBRSIZE || pp->mediasize < pp->sectorsize) return (ENOSPC); + if (pp->sectorsize > 4096) + return (ENXIO); /* Check that there's a MBR. */ buf = g_read_data(cp, 0L, pp->sectorsize, &error); if (buf == NULL) return (error); - res = le16dec(buf + DOSMAGICOFFSET); + + /* We goto out on mismatch. */ + res = ENXIO; + + magic = le16dec(buf + DOSMAGICOFFSET); + if (magic != DOSMAGIC) + goto out; + + for (index = 0; index < NDOSPART; index++) { + p = buf + DOSPARTOFF + index * DOSPARTSIZE; + if (p[0] != 0 && p[0] != 0x80) + goto out; + } + + /* Match. */ + res = G_PART_PROBE_PRI_NORM; + + out: g_free(buf); - return ((res == DOSMAGIC) ? G_PART_PROBE_PRI_NORM : ENXIO); + return (res); } static int @@ -305,8 +325,6 @@ g_part_mbr_read(struct g_part_table *basetable, struct g_consumer *cp) ent.dp_size = le32dec(p + 12); if (ent.dp_typ == 0 || ent.dp_typ == DOSPTYP_PMBR) continue; - if (ent.dp_flag != 0 && ent.dp_flag != 0x80) - continue; if (ent.dp_start == 0 || ent.dp_size == 0) continue; sectors = ent.dp_esect & 0x3f; |