From 779d2d851ee5dbd4c759bb973113373897d3adce Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 13 Nov 2008 19:34:41 +0100 Subject: [PATCH] volume_id: always check for all filesystem types and skip conflicting results We probe for all known filesystems to find conflicting signatures. If we find multiple matching signatures and one of the detected filesystem types claims that it can not co-exist with any other filesystem type, we do not return a probing result. We can not afford to mount a volume with the wrong filesystem code and possibly corrupt it. Linux ssytems have the problem of dozens of possible filesystem types, and volumes with left-over signatures from former filesystem types. Invalid signature need to be removed from the volume to make the filesystem detection successful. We do not want to read that many bytes from probed floppies, skip volumes smaller than a usual floppy disk. --- extras/volume_id/lib/fat.c | 3 +- extras/volume_id/lib/libvolume_id-private.h | 1 + extras/volume_id/lib/linux_swap.c | 2 + extras/volume_id/lib/volume_id.c | 52 +++++++++++++++++++-- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/extras/volume_id/lib/fat.c b/extras/volume_id/lib/fat.c index e30318cf0..2d98b65b5 100644 --- a/extras/volume_id/lib/fat.c +++ b/extras/volume_id/lib/fat.c @@ -497,6 +497,7 @@ fat32: found: volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); id->type = "vfat"; - + /* we think this is fat, but we make sure no other signatures are found */ + id->force_unique_result = 1; return 0; } diff --git a/extras/volume_id/lib/libvolume_id-private.h b/extras/volume_id/lib/libvolume_id-private.h index 14f7568fe..1b4a782b6 100644 --- a/extras/volume_id/lib/libvolume_id-private.h +++ b/extras/volume_id/lib/libvolume_id-private.h @@ -120,6 +120,7 @@ struct volume_id { uint8_t *seekbuf; uint64_t seekbuf_off; size_t seekbuf_len; + int force_unique_result; }; /* utils */ diff --git a/extras/volume_id/lib/linux_swap.c b/extras/volume_id/lib/linux_swap.c index c4beeab97..1698e9dbf 100644 --- a/extras/volume_id/lib/linux_swap.c +++ b/extras/volume_id/lib/linux_swap.c @@ -97,5 +97,7 @@ found_label: found: volume_id_set_usage(id, VOLUME_ID_OTHER); + /* we think this is swap, but we make sure no other signatures are found */ + id->force_unique_result = 1; return 0; } diff --git a/extras/volume_id/lib/volume_id.c b/extras/volume_id/lib/volume_id.c index 8f22509ca..e4d2ed4cf 100644 --- a/extras/volume_id/lib/volume_id.c +++ b/extras/volume_id/lib/volume_id.c @@ -369,9 +369,12 @@ int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size) info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size); - for (i = 0; i < ARRAY_SIZE(prober_raid); i++) - if (prober_raid[i].prober(id, off, size) == 0) + for (i = 0; i < ARRAY_SIZE(prober_raid); i++) { + if (prober_raid[i].prober(id, off, size) == 0) { + info("signature '%s' detected\n", id->type); goto found; + } + } return -1; found: @@ -402,11 +405,50 @@ int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size); - for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) - if (prober_filesystem[i].prober(id, off, size) == 0) + /* + * We probe for all known filesystems to find conflicting signatures. If + * we find multiple matching signatures and one of the detected filesystem + * types claims that it can not co-exist with any other filesystem type, + * we do not return a probing result. + * + * We can not afford to mount a volume with the wrong filesystem code and + * possibly corrupt it. Linux ssytems have the problem of dozens of possible + * filesystem types, and volumes with left-over signatures from former + * filesystem types. Invalid signature need to be removed from the volume + * to make the filesystem detection successful. + * + * We do not want to read that many bytes from probed floppies, skip volumes + * smaller than a usual floppy disk + */ + if (size > 1440 * 1024) { + int found = 0; + int force_unique_result = 0; + + for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { + int match; + + match = (prober_filesystem[i].prober(id, off, size) == 0); + if (match) { + info("signature '%s' detected\n", id->type); + if (id->force_unique_result) + force_unique_result = id->force_unique_result; + if (found && force_unique_result) { + info("conflicting signatures found, skip results\n"); + return -1; + } + found = 1; + } + } + } + + /* return the first match */ + for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { + if (prober_filesystem[i].prober(id, off, size) == 0) { + info("signature '%s' detected\n", id->type); goto found; + } + } return -1; - found: /* If recognized, we free the allocated buffers */ volume_id_free_buffer(id); -- 2.30.2