From e7f0f5d3a80324e1430e979b0a170ded77b380e2 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
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 <kzak@redhat.com>
---
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