graid: Avoid tasting devices with small sector sizes

The RAID metadata parsers effectively assume a sector size of 512 bytes
or larger, but md(4) devices can be created with a sector size that's
any power of 2.  Add some seatbelts to graid tasting routines to ensure
that the requested sector(s) are large enough for the device to
plausibly contain RAID metadata.

Reported by:	syzbot+f43583c9bf8357c8b56f@syzkaller.appspotmail.com
Reported by:	syzbot+537dd9f22b91b698e161@syzkaller.appspotmail.com
Reported by:	syzbot+51509dd48871c57c6e47@syzkaller.appspotmail.com
Reported by:	syzbot+c882a31037ea2a54ff63@syzkaller.appspotmail.com
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Mark Johnston 2021-08-31 17:09:52 -04:00
parent 3138392a46
commit 9e9ba9c73d
6 changed files with 13 additions and 4 deletions

View File

@ -1046,8 +1046,11 @@ ddf_meta_read(struct g_consumer *cp, struct ddf_meta *meta)
uint32_t val;
ddf_meta_free(meta);
pp = cp->provider;
ss = meta->sectorsize = pp->sectorsize;
if (ss < sizeof(*hdr))
return (ENXIO);
/* Read anchor block. */
abuf = g_read_data(cp, pp->mediasize - ss, ss, &error);
if (abuf == NULL) {

View File

@ -593,7 +593,8 @@ intel_meta_read(struct g_consumer *cp)
uint32_t checksum, *ptr;
pp = cp->provider;
if (pp->sectorsize < sizeof(*meta))
return (NULL);
/* Read the anchor sector. */
buf = g_read_data(cp,
pp->mediasize - pp->sectorsize * 2, pp->sectorsize, &error);

View File

@ -270,7 +270,8 @@ jmicron_meta_read(struct g_consumer *cp)
uint16_t checksum, *ptr;
pp = cp->provider;
if (pp->sectorsize < sizeof(*meta))
return (NULL);
/* Read the anchor sector. */
buf = g_read_data(cp,
pp->mediasize - pp->sectorsize, pp->sectorsize, &error);

View File

@ -250,7 +250,8 @@ nvidia_meta_read(struct g_consumer *cp)
uint32_t checksum, *ptr;
pp = cp->provider;
if (pp->sectorsize < sizeof(*meta))
return (NULL);
/* Read the anchor sector. */
buf = g_read_data(cp,
pp->mediasize - 2 * pp->sectorsize, pp->sectorsize, &error);

View File

@ -344,6 +344,8 @@ promise_meta_read(struct g_consumer *cp, struct promise_raid_conf **metaarr)
pp = cp->provider;
subdisks = 0;
if (pp->sectorsize * 4 < sizeof(*meta))
return (subdisks);
if (pp->sectorsize * 4 > maxphys) {
G_RAID_DEBUG(1, "%s: Blocksize is too big.", pp->name);
return (subdisks);

View File

@ -271,7 +271,8 @@ sii_meta_read(struct g_consumer *cp)
uint16_t checksum, *ptr;
pp = cp->provider;
if (pp->sectorsize < sizeof(*meta))
return (NULL);
/* Read the anchor sector. */
buf = g_read_data(cp,
pp->mediasize - pp->sectorsize, pp->sectorsize, &error);