From: Karel Zak Date: Mon, 18 Jan 2010 11:50:36 +0000 (+0100) Subject: libblkid: restrict RAID/FS proving for small devices (1.4MiB) X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=108013b4178a6ad992d4c86fffb0d9351b8c02c5;p=util-linux libblkid: restrict RAID/FS proving for small devices (1.4MiB) - don't ignore @size in blkid_probe_set_device() - ignore extremely small devices (<= 1024 bytes, e.g. extended partitions) - don't use safe probing for small devices - don't probe for RAIDs on small devices Signed-off-by: Karel Zak --- diff --git a/shlibs/blkid/src/blkidP.h b/shlibs/blkid/src/blkidP.h index 90900e27..20cf765a 100644 --- a/shlibs/blkid/src/blkidP.h +++ b/shlibs/blkid/src/blkidP.h @@ -357,7 +357,9 @@ extern blkid_dev blkid_new_dev(void); extern void blkid_free_dev(blkid_dev dev); /* probe.c */ -unsigned char *blkid_probe_get_buffer(blkid_probe pr, +extern int blkid_probe_is_tiny(blkid_probe pr); + +extern unsigned char *blkid_probe_get_buffer(blkid_probe pr, blkid_loff_t off, blkid_loff_t len); extern unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector); diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 7ed80072..6aad7ab4 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -471,17 +471,23 @@ int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[ } /* + * @off: offset within probing area + * @len: size of requested buffer + * + * The probing area is between pr->off and pr->size. The @off = 0 is pr->off, the + * max @len is pr->size. + * * Note that we have two offsets: * * 1/ general device offset (pr->off), that's useful for example when we * probe a partition from whole disk image: - * blkid-low --offset disk.img + * blkid -O -S disk.img * - * 2/ buffer offset (the 'off' argument), that useful for offsets in + * 2/ buffer offset (the @off argument), that useful for offsets in * superbloks, ... * - * That means never use lseek(fd, 0, SEEK_SET), the zero position is always - * pr->off, so lseek(fd, pr->off, SEEK_SET). + * That means never use lseek(fd, 0, SEEK_SET), the zero position is always + * pr->off, so lseek(fd, pr->off, SEEK_SET). * */ unsigned char *blkid_probe_get_buffer(blkid_probe pr, @@ -494,6 +500,13 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, printf("unexpected offset or length of buffer requested\n")); return NULL; } + + if (off + len > pr->size) + return NULL; + + DBG(DEBUG_LOWPROBE, + printf("\tbuffer: offset=%jd size=%jd\n", off, len)); + if (off + len <= BLKID_SB_BUFSIZ) { if (!pr->sbbuf) { pr->sbbuf = malloc(BLKID_SB_BUFSIZ); @@ -525,7 +538,6 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, } if (newbuf || off < pr->buf_off || off + len > pr->buf_off + pr->buf_len) { - if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) return NULL; @@ -539,6 +551,14 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, } } +/* + * Small devices need a special care. + */ +int blkid_probe_is_tiny(blkid_probe pr) +{ + return (pr && pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode)); +} + /** * blkid_probe_set_device: * @pr: probe @@ -589,6 +609,13 @@ int blkid_probe_set_device(blkid_probe pr, int fd, if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) pr->devno = sb.st_rdev; + + if (pr->off > pr->size) + goto err; + + /* The probing area cannot be larger than whole device, pr->off + * is offset within the device */ + pr->size -= pr->off; } if (!pr->size) diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c index e77c511d..dbb48562 100644 --- a/shlibs/blkid/src/superblocks/superblocks.c +++ b/shlibs/blkid/src/superblocks/superblocks.c @@ -310,6 +310,12 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) printf("--> starting probing loop [SUBLKS idx=%d]\n", chn->idx)); + if (pr->size <= 1024 && !S_ISCHR(pr->mode)) + /* Ignore very very small block devices or regular files (e.g. + * extended partitions). Note that size of the UBI char devices + * is 1 byte */ + return 1; + i = chn->idx + 1; for ( ; i < ARRAY_SIZE(idinfos); i++) { @@ -327,6 +333,12 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) id = idinfos[i]; mag = id->magics ? &id->magics[0] : NULL; + /* don't probe for RAIDs on floppies */ + if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) + continue; + + DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name)); + /* try to detect by magic string */ while(mag && mag->magic) { unsigned char *buf; @@ -337,8 +349,8 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) if (buf && !memcmp(mag->magic, buf + (mag->sboff & 0x3ff), mag->len)) { DBG(DEBUG_LOWPROBE, printf( - "%s: magic sboff=%u, kboff=%ld\n", - id->name, mag->sboff, mag->kboff)); + "\tmagic sboff=%u, kboff=%ld\n", + mag->sboff, mag->kboff)); hasmag = 1; off += mag->sboff & 0x3ff; break; @@ -352,8 +364,7 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) /* final check by probing function */ if (id->probefunc) { - DBG(DEBUG_LOWPROBE, printf( - "%s: call probefunc()\n", id->name)); + DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n")); if (id->probefunc(pr, mag) != 0) continue; } @@ -393,6 +404,9 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) * The function does not check for filesystems when a RAID or crypto signature * is detected. The function also does not check for collision between RAIDs * and crypto devices. The first detected RAID or crypto device is returned. + * + * The function does not probe for ambivalent results on very small devices + * (e.g. floppies), on small devices the first detected filesystem is returned. */ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) { @@ -404,6 +418,11 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) int rc; while ((rc = superblocks_probe(pr, chn)) == 0) { + + if (blkid_probe_is_tiny(pr) && !count) + /* floppy or so -- returns the first result. */ + return 0; + if (!count) { /* save the first result */ nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);