dcavalca / rpms / mdadm

Forked from rpms/mdadm 3 years ago
Clone

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

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