From e7f0f5d3a80324e1430e979b0a170ded77b380e2 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 13 Oct 2020 16:19:20 +0200 Subject: libblkid: make Atari more robust * ignore large disks * check in-table stored device size * check bad sectors list * check partition dimensions against in-table device size Addresses: https://github.com/karelzak/util-linux/issues/1159 Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2060030 Upstream: http://github.com/util-linux/util-linux/commit/282ceadc3a72fc07dd0388b8880fd751490bb87f Signed-off-by: Karel Zak --- libblkid/src/partitions/atari.c | 66 ++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/libblkid/src/partitions/atari.c b/libblkid/src/partitions/atari.c index b469ef5a1..c3f77117a 100644 --- a/libblkid/src/partitions/atari.c +++ b/libblkid/src/partitions/atari.c @@ -74,16 +74,27 @@ static int linux_isalnum(unsigned char c) { #define IS_ACTIVE(partdef) ((partdef).flags & 1) -#define IS_PARTDEF_VALID(partdef, hdsize) \ - ( \ - (partdef).flags & 1 && \ - isalnum((partdef).id[0]) && \ - isalnum((partdef).id[1]) && \ - isalnum((partdef).id[2]) && \ - be32_to_cpu((partdef).start) <= (hdsize) && \ - be32_to_cpu((partdef).start) + \ - be32_to_cpu((partdef).size) <= (hdsize) \ - ) +static int is_valid_dimension(uint32_t start, uint32_t size, uint32_t maxoff) +{ + uint64_t end = start + size; + + return end >= start + && 0 < start && start <= maxoff + && 0 < size && size <= maxoff + && 0 < end && end <= maxoff; +} + +static int is_valid_partition(struct atari_part_def *part, uint32_t maxoff) +{ + uint32_t start = be32_to_cpu(part->start), + size = be32_to_cpu(part->size); + + return (part->flags & 1) + && isalnum(part->id[0]) + && isalnum(part->id[1]) + && isalnum(part->id[2]) + && is_valid_dimension(start, size, maxoff); +} static int is_id_common(char *id) { @@ -184,12 +195,20 @@ static int probe_atari_pt(blkid_probe pr, unsigned i; int has_xgm = 0; int rc = 0; - off_t hdsize; + uint32_t rssize; /* size in sectors from root sector */ + uint64_t size; /* size in sectors from system */ /* Atari partition is not defined for other sector sizes */ if (blkid_probe_get_sectorsize(pr) != 512) goto nothing; + size = blkid_probe_get_size(pr) / 512; + + /* Atari is not well defined to support large disks */ + if (size > INT32_MAX) + goto nothing; + + /* read root sector */ rs = (struct atari_rootsector *) blkid_probe_get_sector(pr, 0); if (!rs) { if (errno) @@ -197,17 +216,29 @@ static int probe_atari_pt(blkid_probe pr, goto nothing; } - hdsize = blkid_probe_get_size(pr) / 512; + rssize = be32_to_cpu(rs->hd_size); + + /* check number of sectors stored in the root sector */ + if (rssize < 2 || rssize > size) + goto nothing; + + /* check list of bad blocks */ + if ((rs->bsl_start || rs->bsl_len) + && !is_valid_dimension(be32_to_cpu(rs->bsl_start), + be32_to_cpu(rs->bsl_len), + rssize)) + goto nothing; /* * At least one valid partition required */ for (i = 0; i < 4; i++) { - if (IS_PARTDEF_VALID(rs->part[i], hdsize)) { - blkid_probe_set_magic(pr, - offsetof(struct atari_rootsector, part[i]), - sizeof(rs->part[i].flags) + sizeof(rs->part[i].id), - (unsigned char *) &rs->part[i]); + if (is_valid_partition(&rs->part[i], rssize)) { + if (blkid_probe_set_magic(pr, + offsetof(struct atari_rootsector, part[i]), + sizeof(rs->part[i].flags) + sizeof(rs->part[i].id), + (unsigned char *) &rs->part[i])) + goto err; break; } } @@ -234,7 +265,6 @@ static int probe_atari_pt(blkid_probe pr, blkid_partlist_increment_partno(ls); continue; } - if (!memcmp(p->id, "XGM", 3)) { has_xgm = 1; rc = parse_extended(pr, ls, tab, p); -- 2.36.1