From owner-svn-src-stable-8@FreeBSD.ORG Sat Nov 21 14:53:09 2009 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 64EE2106566B; Sat, 21 Nov 2009 14:53:09 +0000 (UTC) (envelope-from rnoland@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 524DE8FC19; Sat, 21 Nov 2009 14:53:09 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nALEr949082604; Sat, 21 Nov 2009 14:53:09 GMT (envelope-from rnoland@svn.freebsd.org) Received: (from rnoland@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nALEr8XD082602; Sat, 21 Nov 2009 14:53:08 GMT (envelope-from rnoland@svn.freebsd.org) Message-Id: <200911211453.nALEr8XD082602@svn.freebsd.org> From: Robert Noland Date: Sat, 21 Nov 2009 14:53:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r199630 - stable/8/sys/geom/part X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 21 Nov 2009 14:53:09 -0000 Author: rnoland Date: Sat Nov 21 14:53:08 2009 New Revision: 199630 URL: http://svn.freebsd.org/changeset/base/199630 Log: MFC r199017,199228 Fix handling of GPT headers when size is > 92 bytes. This should address reading GPT headers written by opensolaris. Modified: stable/8/sys/geom/part/g_part_gpt.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/geom/part/g_part_gpt.c ============================================================================== --- stable/8/sys/geom/part/g_part_gpt.c Sat Nov 21 14:28:32 2009 (r199629) +++ stable/8/sys/geom/part/g_part_gpt.c Sat Nov 21 14:53:08 2009 (r199630) @@ -73,7 +73,7 @@ enum gpt_state { struct g_part_gpt_table { struct g_part_table base; u_char mbr[MBRSIZE]; - struct gpt_hdr hdr; + struct gpt_hdr *hdr; quad_t lba[GPT_ELT_COUNT]; enum gpt_state state[GPT_ELT_COUNT]; }; @@ -143,13 +143,12 @@ static struct uuid gpt_uuid_linux_swap = static struct uuid gpt_uuid_mbr = GPT_ENT_TYPE_MBR; static struct uuid gpt_uuid_unused = GPT_ENT_TYPE_UNUSED; -static void +static struct gpt_hdr * gpt_read_hdr(struct g_part_gpt_table *table, struct g_consumer *cp, - enum gpt_elt elt, struct gpt_hdr *hdr) + enum gpt_elt elt) { - struct uuid uuid; + struct gpt_hdr *buf, *hdr; struct g_provider *pp; - char *buf; quad_t lba, last; int error; uint32_t crc, sz; @@ -161,63 +160,75 @@ gpt_read_hdr(struct g_part_gpt_table *ta buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, pp->sectorsize, &error); if (buf == NULL) - return; - bcopy(buf, hdr, sizeof(*hdr)); - if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) != 0) - return; + return (NULL); + hdr = NULL; + if (memcmp(buf->hdr_sig, GPT_HDR_SIG, sizeof(buf->hdr_sig)) != 0) + goto fail; table->state[elt] = GPT_STATE_CORRUPT; - sz = le32toh(hdr->hdr_size); + sz = le32toh(buf->hdr_size); if (sz < 92 || sz > pp->sectorsize) - return; - crc = le32toh(hdr->hdr_crc_self); - hdr->hdr_crc_self = 0; - if (crc32(hdr, sz) != crc) - return; + goto fail; + + hdr = g_malloc(sz, M_WAITOK | M_ZERO); + bcopy(buf, hdr, sz); hdr->hdr_size = sz; + + crc = le32toh(buf->hdr_crc_self); + buf->hdr_crc_self = 0; + if (crc32(buf, sz) != crc) + goto fail; hdr->hdr_crc_self = crc; table->state[elt] = GPT_STATE_INVALID; - hdr->hdr_revision = le32toh(hdr->hdr_revision); + hdr->hdr_revision = le32toh(buf->hdr_revision); if (hdr->hdr_revision < 0x00010000) - return; - hdr->hdr_lba_self = le64toh(hdr->hdr_lba_self); + goto fail; + hdr->hdr_lba_self = le64toh(buf->hdr_lba_self); if (hdr->hdr_lba_self != table->lba[elt]) - return; - hdr->hdr_lba_alt = le64toh(hdr->hdr_lba_alt); + goto fail; + hdr->hdr_lba_alt = le64toh(buf->hdr_lba_alt); /* Check the managed area. */ - hdr->hdr_lba_start = le64toh(hdr->hdr_lba_start); + hdr->hdr_lba_start = le64toh(buf->hdr_lba_start); if (hdr->hdr_lba_start < 2 || hdr->hdr_lba_start >= last) - return; - hdr->hdr_lba_end = le64toh(hdr->hdr_lba_end); + goto fail; + hdr->hdr_lba_end = le64toh(buf->hdr_lba_end); if (hdr->hdr_lba_end < hdr->hdr_lba_start || hdr->hdr_lba_end >= last) - return; + goto fail; /* Check the table location and size of the table. */ - hdr->hdr_entries = le32toh(hdr->hdr_entries); - hdr->hdr_entsz = le32toh(hdr->hdr_entsz); + hdr->hdr_entries = le32toh(buf->hdr_entries); + hdr->hdr_entsz = le32toh(buf->hdr_entsz); if (hdr->hdr_entries == 0 || hdr->hdr_entsz < 128 || (hdr->hdr_entsz & 7) != 0) - return; - hdr->hdr_lba_table = le64toh(hdr->hdr_lba_table); + goto fail; + hdr->hdr_lba_table = le64toh(buf->hdr_lba_table); if (hdr->hdr_lba_table < 2 || hdr->hdr_lba_table >= last) - return; + goto fail; if (hdr->hdr_lba_table >= hdr->hdr_lba_start && hdr->hdr_lba_table <= hdr->hdr_lba_end) - return; + goto fail; lba = hdr->hdr_lba_table + (hdr->hdr_entries * hdr->hdr_entsz + pp->sectorsize - 1) / pp->sectorsize - 1; if (lba >= last) - return; + goto fail; if (lba >= hdr->hdr_lba_start && lba <= hdr->hdr_lba_end) - return; + goto fail; table->state[elt] = GPT_STATE_OK; - le_uuid_dec(&hdr->hdr_uuid, &uuid); - hdr->hdr_uuid = uuid; - hdr->hdr_crc_table = le32toh(hdr->hdr_crc_table); + le_uuid_dec(&buf->hdr_uuid, &hdr->hdr_uuid); + hdr->hdr_crc_table = le32toh(buf->hdr_crc_table); + + g_free(buf); + return (hdr); + + fail: + if (hdr != NULL) + g_free(hdr); + g_free(buf); + return (NULL); } static struct gpt_ent * @@ -230,6 +241,9 @@ gpt_read_tbl(struct g_part_gpt_table *ta unsigned int idx, sectors, tblsz; int error; + if (hdr == NULL) + return (NULL); + pp = cp->provider; table->lba[elt] = hdr->hdr_lba_table; @@ -271,6 +285,9 @@ static int gpt_matched_hdrs(struct gpt_hdr *pri, struct gpt_hdr *sec) { + if (pri == NULL || sec == NULL) + return (0); + if (!EQUUID(&pri->hdr_uuid, &sec->hdr_uuid)) return (0); return ((pri->hdr_revision == sec->hdr_revision && @@ -427,17 +444,20 @@ g_part_gpt_create(struct g_part_table *b table->lba[GPT_ELT_SECHDR] = last; table->lba[GPT_ELT_SECTBL] = last - tblsz; - bcopy(GPT_HDR_SIG, table->hdr.hdr_sig, sizeof(table->hdr.hdr_sig)); - table->hdr.hdr_revision = GPT_HDR_REVISION; - table->hdr.hdr_size = offsetof(struct gpt_hdr, padding); - table->hdr.hdr_lba_start = 2 + tblsz; - table->hdr.hdr_lba_end = last - tblsz - 1; - kern_uuidgen(&table->hdr.hdr_uuid, 1); - table->hdr.hdr_entries = basetable->gpt_entries; - table->hdr.hdr_entsz = sizeof(struct gpt_ent); + /* Allocate space for the header */ + table->hdr = g_malloc(sizeof(struct gpt_hdr), M_WAITOK | M_ZERO); + + bcopy(GPT_HDR_SIG, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); + table->hdr->hdr_revision = GPT_HDR_REVISION; + table->hdr->hdr_size = offsetof(struct gpt_hdr, padding); + table->hdr->hdr_lba_start = 2 + tblsz; + table->hdr->hdr_lba_end = last - tblsz - 1; + kern_uuidgen(&table->hdr->hdr_uuid, 1); + table->hdr->hdr_entries = basetable->gpt_entries; + table->hdr->hdr_entsz = sizeof(struct gpt_ent); - basetable->gpt_first = table->hdr.hdr_lba_start; - basetable->gpt_last = table->hdr.hdr_lba_end; + basetable->gpt_first = table->hdr->hdr_lba_start; + basetable->gpt_last = table->hdr->hdr_lba_end; return (0); } @@ -582,7 +602,7 @@ g_part_gpt_probe(struct g_part_table *ta static int g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp) { - struct gpt_hdr prihdr, sechdr; + struct gpt_hdr *prihdr, *sechdr; struct gpt_ent *tbl, *pritbl, *sectbl; struct g_provider *pp; struct g_part_gpt_table *table; @@ -601,18 +621,18 @@ g_part_gpt_read(struct g_part_table *bas g_free(buf); /* Read the primary header and table. */ - gpt_read_hdr(table, cp, GPT_ELT_PRIHDR, &prihdr); + prihdr = gpt_read_hdr(table, cp, GPT_ELT_PRIHDR); if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK) { - pritbl = gpt_read_tbl(table, cp, GPT_ELT_PRITBL, &prihdr); + pritbl = gpt_read_tbl(table, cp, GPT_ELT_PRITBL, prihdr); } else { table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; pritbl = NULL; } /* Read the secondary header and table. */ - gpt_read_hdr(table, cp, GPT_ELT_SECHDR, &sechdr); + sechdr = gpt_read_hdr(table, cp, GPT_ELT_SECHDR); if (table->state[GPT_ELT_SECHDR] == GPT_STATE_OK) { - sectbl = gpt_read_tbl(table, cp, GPT_ELT_SECTBL, &sechdr); + sectbl = gpt_read_tbl(table, cp, GPT_ELT_SECTBL, sechdr); } else { table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; sectbl = NULL; @@ -635,13 +655,17 @@ g_part_gpt_read(struct g_part_table *bas */ if (table->state[GPT_ELT_PRIHDR] == GPT_STATE_OK && table->state[GPT_ELT_SECHDR] == GPT_STATE_OK && - !gpt_matched_hdrs(&prihdr, &sechdr)) { + !gpt_matched_hdrs(prihdr, sechdr)) { if (table->state[GPT_ELT_PRITBL] == GPT_STATE_OK) { table->state[GPT_ELT_SECHDR] = GPT_STATE_INVALID; table->state[GPT_ELT_SECTBL] = GPT_STATE_MISSING; + g_free(sechdr); + sechdr = NULL; } else { table->state[GPT_ELT_PRIHDR] = GPT_STATE_INVALID; table->state[GPT_ELT_PRITBL] = GPT_STATE_MISSING; + g_free(prihdr); + prihdr = NULL; } } @@ -651,6 +675,8 @@ g_part_gpt_read(struct g_part_table *bas printf("GEOM: %s: using the secondary instead -- recovery " "strongly advised.\n", pp->name); table->hdr = sechdr; + if (prihdr != NULL) + g_free(prihdr); tbl = sectbl; if (pritbl != NULL) g_free(pritbl); @@ -662,14 +688,16 @@ g_part_gpt_read(struct g_part_table *bas "suggested.\n", pp->name); } table->hdr = prihdr; + if (sechdr != NULL) + g_free(sechdr); tbl = pritbl; if (sectbl != NULL) g_free(sectbl); } - basetable->gpt_first = table->hdr.hdr_lba_start; - basetable->gpt_last = table->hdr.hdr_lba_end; - basetable->gpt_entries = table->hdr.hdr_entries; + basetable->gpt_first = table->hdr->hdr_lba_start; + basetable->gpt_last = table->hdr->hdr_lba_end; + basetable->gpt_entries = table->hdr->hdr_entries; for (index = basetable->gpt_entries - 1; index >= 0; index--) { if (EQUUID(&tbl[index].ent_type, &gpt_uuid_unused)) @@ -729,7 +757,7 @@ g_part_gpt_write(struct g_part_table *ba pp = cp->provider; table = (struct g_part_gpt_table *)basetable; - tlbsz = (table->hdr.hdr_entries * table->hdr.hdr_entsz + + tlbsz = (table->hdr->hdr_entries * table->hdr->hdr_entsz + pp->sectorsize - 1) / pp->sectorsize; /* Write the PMBR */ @@ -743,21 +771,21 @@ g_part_gpt_write(struct g_part_table *ba /* Allocate space for the header and entries. */ buf = g_malloc((tlbsz + 1) * pp->sectorsize, M_WAITOK | M_ZERO); - memcpy(buf, table->hdr.hdr_sig, sizeof(table->hdr.hdr_sig)); - le32enc(buf + 8, table->hdr.hdr_revision); - le32enc(buf + 12, table->hdr.hdr_size); - le64enc(buf + 40, table->hdr.hdr_lba_start); - le64enc(buf + 48, table->hdr.hdr_lba_end); - le_uuid_enc(buf + 56, &table->hdr.hdr_uuid); - le32enc(buf + 80, table->hdr.hdr_entries); - le32enc(buf + 84, table->hdr.hdr_entsz); + memcpy(buf, table->hdr->hdr_sig, sizeof(table->hdr->hdr_sig)); + le32enc(buf + 8, table->hdr->hdr_revision); + le32enc(buf + 12, table->hdr->hdr_size); + le64enc(buf + 40, table->hdr->hdr_lba_start); + le64enc(buf + 48, table->hdr->hdr_lba_end); + le_uuid_enc(buf + 56, &table->hdr->hdr_uuid); + le32enc(buf + 80, table->hdr->hdr_entries); + le32enc(buf + 84, table->hdr->hdr_entsz); LIST_FOREACH(baseentry, &basetable->gpt_entry, gpe_entry) { if (baseentry->gpe_deleted) continue; entry = (struct g_part_gpt_entry *)baseentry; index = baseentry->gpe_index - 1; - bp = buf + pp->sectorsize + table->hdr.hdr_entsz * index; + bp = buf + pp->sectorsize + table->hdr->hdr_entsz * index; le_uuid_enc(bp, &entry->ent.ent_type); le_uuid_enc(bp + 16, &entry->ent.ent_uuid); le64enc(bp + 32, entry->ent.ent_lba_start); @@ -768,7 +796,7 @@ g_part_gpt_write(struct g_part_table *ba } crc = crc32(buf + pp->sectorsize, - table->hdr.hdr_entries * table->hdr.hdr_entsz); + table->hdr->hdr_entries * table->hdr->hdr_entsz); le32enc(buf + 88, crc); /* Write primary meta-data. */ @@ -776,7 +804,7 @@ g_part_gpt_write(struct g_part_table *ba le64enc(buf + 24, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_self. */ le64enc(buf + 32, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_alt. */ le64enc(buf + 72, table->lba[GPT_ELT_PRITBL]); /* hdr_lba_table. */ - crc = crc32(buf, table->hdr.hdr_size); + crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, @@ -793,7 +821,7 @@ g_part_gpt_write(struct g_part_table *ba le64enc(buf + 24, table->lba[GPT_ELT_SECHDR]); /* hdr_lba_self. */ le64enc(buf + 32, table->lba[GPT_ELT_PRIHDR]); /* hdr_lba_alt. */ le64enc(buf + 72, table->lba[GPT_ELT_SECTBL]); /* hdr_lba_table. */ - crc = crc32(buf, table->hdr.hdr_size); + crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize,