dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

Blame SOURCES/0083-Detect-too-small-device-error-rather-than-underflow-.patch

790dca
From 2cf0433063203fca10d26629c9e090b51fb1d806 Mon Sep 17 00:00:00 2001
790dca
From: David Favro <dfavro@meta-dynamic.com>
790dca
Date: Sat, 23 May 2020 08:24:59 -0400
790dca
Subject: [PATCH 083/108] Detect too-small device: error rather than
790dca
 underflow/crash
790dca
790dca
For 1.x metadata, when the user requested creation of an array on
790dca
component devices that were too small even to hold the superblock,
790dca
an undetected integer wraparound (underflow) resulted in an enormous
790dca
computed size which resulted in various follow-on errors such as
790dca
floating-point exception.
790dca
790dca
This patch detects this condition, prints a reasonable diagnostic
790dca
message, and refuses to continue.
790dca
790dca
Signed-off-by: David Favro <dfavro@meta-dynamic.com>
790dca
Signed-off-by: Jes Sorensen <jsorensen@fb.com>
790dca
---
790dca
 super1.c | 19 ++++++++++++++-----
790dca
 1 file changed, 14 insertions(+), 5 deletions(-)
790dca
790dca
diff --git a/super1.c b/super1.c
790dca
index e0d80be..7664883 100644
790dca
--- a/super1.c
790dca
+++ b/super1.c
790dca
@@ -2753,6 +2753,7 @@ static int validate_geometry1(struct supertype *st, int level,
790dca
 	unsigned long long ldsize, devsize;
790dca
 	int bmspace;
790dca
 	unsigned long long headroom;
790dca
+	unsigned long long overhead;
790dca
 	int fd;
790dca
 
790dca
 	if (level == LEVEL_CONTAINER) {
790dca
@@ -2785,10 +2786,6 @@ static int validate_geometry1(struct supertype *st, int level,
790dca
 	close(fd);
790dca
 
790dca
 	devsize = ldsize >> 9;
790dca
-	if (devsize < 24) {
790dca
-		*freesize = 0;
790dca
-		return 0;
790dca
-	}
790dca
 
790dca
 	/* creating:  allow suitable space for bitmap or PPL */
790dca
 	if (consistency_policy == CONSISTENCY_POLICY_PPL)
790dca
@@ -2829,15 +2826,27 @@ static int validate_geometry1(struct supertype *st, int level,
790dca
 	case 0: /* metadata at end.  Round down and subtract space to reserve */
790dca
 		devsize = (devsize & ~(4ULL*2-1));
790dca
 		/* space for metadata, bblog, bitmap/ppl */
790dca
-		devsize -= 8*2 + 8 + bmspace;
790dca
+		overhead = 8*2 + 8 + bmspace;
790dca
+		if (devsize < overhead) /* detect underflow */
790dca
+			goto dev_too_small_err;
790dca
+		devsize -= overhead;
790dca
 		break;
790dca
 	case 1:
790dca
 	case 2:
790dca
+		if (devsize < data_offset) /* detect underflow */
790dca
+			goto dev_too_small_err;
790dca
 		devsize -= data_offset;
790dca
 		break;
790dca
 	}
790dca
 	*freesize = devsize;
790dca
 	return 1;
790dca
+
790dca
+/* Error condition, device cannot even hold the overhead. */
790dca
+dev_too_small_err:
790dca
+	fprintf(stderr, "device %s is too small (%lluK) for "
790dca
+			"required metadata!\n", subdev, devsize>>1);
790dca
+	*freesize = 0;
790dca
+	return 0;
790dca
 }
790dca
 
790dca
 void *super1_make_v0(struct supertype *st, struct mdinfo *info, mdp_super_t *sb0)
790dca
-- 
790dca
2.7.5
790dca