Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 May 2011 19:59:44 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r221788 - head/sys/geom/part
Message-ID:  <201105111959.p4BJxiN0004096@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Wed May 11 19:59:43 2011
New Revision: 221788
URL: http://svn.freebsd.org/changeset/base/221788

Log:
  Add basic metadata integrity check. In case when partition table was
  probed and read successfull, but it contains invalid values (e.g.
  overlapped partitions, offset or size is out of bounds), then table
  will be rejected.
  
  MFC after:	1 month

Modified:
  head/sys/geom/part/g_part.c

Modified: head/sys/geom/part/g_part.c
==============================================================================
--- head/sys/geom/part/g_part.c	Wed May 11 19:06:09 2011	(r221787)
+++ head/sys/geom/part/g_part.c	Wed May 11 19:59:43 2011	(r221788)
@@ -231,6 +231,48 @@ g_part_geometry(struct g_part_table *tab
 	}
 }
 
+static int
+g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
+{
+	struct g_part_entry *e1, *e2;
+	struct g_provider *pp;
+
+	pp = cp->provider;
+	if (table->gpt_first > table->gpt_last ||
+	    table->gpt_last > pp->mediasize / pp->sectorsize - 1)
+		goto fail;
+
+	LIST_FOREACH(e1, &table->gpt_entry, gpe_entry) {
+		if (e1->gpe_deleted || e1->gpe_internal)
+			continue;
+		if (e1->gpe_start < table->gpt_first ||
+		    e1->gpe_start > table->gpt_last ||
+		    e1->gpe_end < e1->gpe_start ||
+		    e1->gpe_end > table->gpt_last)
+			goto fail;
+		e2 = e1;
+		while ((e2 = LIST_NEXT(e2, gpe_entry)) != NULL) {
+			if (e2->gpe_deleted || e2->gpe_internal)
+				continue;
+			if (e1->gpe_start >= e2->gpe_start &&
+			    e1->gpe_start <= e2->gpe_end)
+				goto fail;
+			if (e1->gpe_end >= e2->gpe_start &&
+			    e1->gpe_end <= e2->gpe_end)
+				goto fail;
+			if (e1->gpe_start < e2->gpe_start &&
+			    e1->gpe_end > e2->gpe_end)
+				goto fail;
+		}
+	}
+	return (0);
+fail:
+	if (bootverbose)
+		printf("GEOM_PART: integrity check failed (%s, %s)\n",
+		    pp->name, table->gpt_scheme->name);
+	return (EINVAL);
+}
+
 struct g_part_entry *
 g_part_new_entry(struct g_part_table *table, int index, quad_t start,
     quad_t end)
@@ -1310,9 +1352,11 @@ g_part_ctl_undo(struct gctl_req *req, st
 	error = G_PART_READ(table, cp);
 	if (error)
 		goto fail;
+	error = g_part_check_integrity(table, cp);
+	if (error)
+		goto fail;
 
 	g_topology_lock();
-
 	LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) {
 		if (!entry->gpe_internal)
 			g_part_new_provider(gp, table, entry);
@@ -1773,6 +1817,9 @@ g_part_taste(struct g_class *mp, struct 
 	error = G_PART_READ(table, cp);
 	if (error)
 		goto fail;
+	error = g_part_check_integrity(table, cp);
+	if (error)
+		goto fail;
 
 	g_topology_lock();
 	LIST_FOREACH(entry, &table->gpt_entry, gpe_entry) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105111959.p4BJxiN0004096>