Blob Blame History Raw
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