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