summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2011-05-11 19:59:43 +0000
committerae <ae@FreeBSD.org>2011-05-11 19:59:43 +0000
commitd529455d7db30a84557af5ad654e469cf9277a6f (patch)
treedaae4efd4c0a523fe99ec557177713f9457a15a5 /sys/geom
parente506954648aa1463322afff9e5709e15a5b6340f (diff)
downloadFreeBSD-src-d529455d7db30a84557af5ad654e469cf9277a6f.zip
FreeBSD-src-d529455d7db30a84557af5ad654e469cf9277a6f.tar.gz
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
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/part/g_part.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 437914a..aa5444e 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -231,6 +231,48 @@ g_part_geometry(struct g_part_table *table, struct g_consumer *cp,
}
}
+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, struct g_part_parms *gpp)
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 g_provider *pp, int flags __unused)
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) {
OpenPOWER on IntegriCloud