]> err.no Git - util-linux/commitdiff
libblkid: restrict RAID/FS proving for small devices (1.4MiB)
authorKarel Zak <kzak@redhat.com>
Mon, 18 Jan 2010 11:50:36 +0000 (12:50 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 18 Jan 2010 11:50:36 +0000 (12:50 +0100)
 - 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 <kzak@redhat.com>
shlibs/blkid/src/blkidP.h
shlibs/blkid/src/probe.c
shlibs/blkid/src/superblocks/superblocks.c

index 90900e27ef543d78fcf1dcf55a7df7a5432e24d6..20cf765ab313db43697841860ec4cfe0a862c829 100644 (file)
@@ -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);
index 7ed800724858d454170da4b8a8c1e386630ee147..6aad7ab458233e35ae2f3aec4ea49b1fa42105b5 100644 (file)
@@ -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  <partition_position> disk.img
+ *                    blkid -O <partition_position> -S <size> 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)
index e77c511dde59855f1eda33b6b4aef859563bab7e..dbb48562da33331e3883732b90f1bdd6437b3099 100644 (file)
@@ -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);