]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: make Atari more robust
authorKarel Zak <kzak@redhat.com>
Tue, 13 Oct 2020 14:19:20 +0000 (16:19 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 13 Oct 2020 14:19:20 +0000 (16:19 +0200)
* 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
Signed-off-by: Karel Zak <kzak@redhat.com>
libblkid/src/partitions/atari.c

index f9404f9e1784ad73cac1e78e757623f48459276e..3f9f4df53acd0fc50812b01f5879219aad3e20ef 100644 (file)
@@ -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,13 +216,24 @@ 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)) {
+               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),
@@ -235,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);