| Summary: | [geom] [panic] graid3 panic: g_read_data: invalid length 262144 | ||
|---|---|---|---|
| Product: | Base System | Reporter: | Rebecca Cran <bcran> |
| Component: | kern | Assignee: | Andrey V. Elsukov <ae> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | Unspecified | ||
| Hardware: | Any | ||
| OS: | Any | ||
|
Description
Rebecca Cran
2010-06-14 14:40:01 UTC
Responsible Changed From-To: freebsd-bugs->freebsd-geom Over to maintainer(s). Responsible Changed From-To: freebsd-geom->ae Take it. Author: ae Date: Wed Jan 12 13:55:01 2011 New Revision: 217305 URL: http://svn.freebsd.org/changeset/base/217305 Log: Sector size can not be greater than MAXPHYS. Since GRAID3 calculates sector size from user-specified block size, report to user about big blocksize. PR: kern/147851 MFC after: 1 week Modified: head/sbin/geom/class/raid3/geom_raid3.c head/sys/geom/raid3/g_raid3.c Modified: head/sbin/geom/class/raid3/geom_raid3.c ============================================================================== --- head/sbin/geom/class/raid3/geom_raid3.c Wed Jan 12 13:16:35 2011 (r217304) +++ head/sbin/geom/class/raid3/geom_raid3.c Wed Jan 12 13:55:01 2011 (r217305) @@ -213,6 +213,11 @@ raid3_label(struct gctl_req *req) md.md_sectorsize = sectorsize * (nargs - 2); md.md_mediasize -= (md.md_mediasize % md.md_sectorsize); + if (md.md_sectorsize > MAXPHYS) { + gctl_error(req, "The blocksize is too big."); + return; + } + /* * Clear last sector first, to spoil all components if device exists. */ Modified: head/sys/geom/raid3/g_raid3.c ============================================================================== --- head/sys/geom/raid3/g_raid3.c Wed Jan 12 13:16:35 2011 (r217304) +++ head/sys/geom/raid3/g_raid3.c Wed Jan 12 13:55:01 2011 (r217305) @@ -2913,6 +2913,10 @@ g_raid3_read_metadata(struct g_consumer cp->provider->name); return (error); } + if (md->md_sectorsize > MAXPHYS) { + G_RAID3_DEBUG(0, "The blocksize is too big."); + return (EINVAL); + } return (0); } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" Author: ae Date: Tue Jan 18 09:52:53 2011 New Revision: 217531 URL: http://svn.freebsd.org/changeset/base/217531 Log: Limit maximum number of GPT entries to 4k. It is most realistic value and can prevent kernel memory exhausting when big value is specified from command line. Split reading and writing operation to several iteration to do not trigger KASSERT when data length is greater than MAXPHYS. PR: kern/144962, kern/147851 MFC after: 2 weeks Modified: head/sys/geom/part/g_part_gpt.c Modified: head/sys/geom/part/g_part_gpt.c ============================================================================== --- head/sys/geom/part/g_part_gpt.c Tue Jan 18 06:24:52 2011 (r217530) +++ head/sys/geom/part/g_part_gpt.c Tue Jan 18 09:52:53 2011 (r217531) @@ -134,7 +134,7 @@ static struct g_part_scheme g_part_gpt_s sizeof(struct g_part_gpt_table), .gps_entrysz = sizeof(struct g_part_gpt_entry), .gps_minent = 128, - .gps_maxent = INT_MAX, + .gps_maxent = 4096, .gps_bootcodesz = MBRSIZE, }; G_PART_SCHEME_DECLARE(g_part_gpt); @@ -317,7 +317,7 @@ gpt_read_tbl(struct g_part_gpt_table *ta struct g_provider *pp; struct gpt_ent *ent, *tbl; char *buf, *p; - unsigned int idx, sectors, tblsz; + unsigned int idx, sectors, tblsz, size; int error; if (hdr == NULL) @@ -329,11 +329,19 @@ gpt_read_tbl(struct g_part_gpt_table *ta table->state[elt] = GPT_STATE_MISSING; tblsz = hdr->hdr_entries * hdr->hdr_entsz; sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize; - buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, - sectors * pp->sectorsize, &error); - if (buf == NULL) - return (NULL); - + buf = g_malloc(sectors * pp->sectorsize, M_WAITOK | M_ZERO); + for (idx = 0; idx < sectors; idx += MAXPHYS / pp->sectorsize) { + size = (sectors - idx > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (sectors - idx) * pp->sectorsize; + p = g_read_data(cp, (table->lba[elt] + idx) * pp->sectorsize, + size, &error); + if (p == NULL) { + g_free(buf); + return (NULL); + } + bcopy(p, buf + idx * pp->sectorsize, size); + g_free(p); + } table->state[elt] = GPT_STATE_CORRUPT; if (crc32(buf, tblsz) != hdr->hdr_crc_table) { g_free(buf); @@ -986,10 +994,15 @@ g_part_gpt_write(struct g_part_table *ba crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); - error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, - buf + pp->sectorsize, tblsz * pp->sectorsize); - if (error) - goto out; + for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) { + error = g_write_data(cp, + (table->lba[GPT_ELT_PRITBL] + index) * pp->sectorsize, + buf + (index + 1) * pp->sectorsize, + (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (tblsz - index) * pp->sectorsize); + if (error) + goto out; + } error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize, buf, pp->sectorsize); if (error) @@ -1003,10 +1016,15 @@ g_part_gpt_write(struct g_part_table *ba crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); - error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize, - buf + pp->sectorsize, tblsz * pp->sectorsize); - if (error) - goto out; + for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) { + error = g_write_data(cp, + (table->lba[GPT_ELT_SECTBL] + index) * pp->sectorsize, + buf + (index + 1) * pp->sectorsize, + (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (tblsz - index) * pp->sectorsize); + if (error) + goto out; + } error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, buf, pp->sectorsize); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" State Changed From-To: open->patched Patched in head/. Author: ae Date: Wed Jan 19 05:13:40 2011 New Revision: 217572 URL: http://svn.freebsd.org/changeset/base/217572 Log: MFC r217305: Sector size can not be greater than MAXPHYS. Since GRAID3 calculates sector size from user-specified block size, report to user about big blocksize. PR: kern/147851 Modified: stable/8/sbin/geom/class/raid3/geom_raid3.c stable/8/sys/geom/raid3/g_raid3.c Directory Properties: stable/8/sbin/geom/ (props changed) stable/8/sbin/geom/class/multipath/ (props changed) stable/8/sbin/geom/class/part/ (props changed) stable/8/sbin/geom/class/sched/gsched.8 (props changed) stable/8/sbin/geom/class/stripe/ (props changed) 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) Modified: stable/8/sbin/geom/class/raid3/geom_raid3.c ============================================================================== --- stable/8/sbin/geom/class/raid3/geom_raid3.c Wed Jan 19 05:08:32 2011 (r217571) +++ stable/8/sbin/geom/class/raid3/geom_raid3.c Wed Jan 19 05:13:40 2011 (r217572) @@ -212,6 +212,11 @@ raid3_label(struct gctl_req *req) md.md_sectorsize = sectorsize * (nargs - 2); md.md_mediasize -= (md.md_mediasize % md.md_sectorsize); + if (md.md_sectorsize > MAXPHYS) { + gctl_error(req, "The blocksize is too big."); + return; + } + /* * Clear last sector first, to spoil all components if device exists. */ Modified: stable/8/sys/geom/raid3/g_raid3.c ============================================================================== --- stable/8/sys/geom/raid3/g_raid3.c Wed Jan 19 05:08:32 2011 (r217571) +++ stable/8/sys/geom/raid3/g_raid3.c Wed Jan 19 05:13:40 2011 (r217572) @@ -2913,6 +2913,10 @@ g_raid3_read_metadata(struct g_consumer cp->provider->name); return (error); } + if (md->md_sectorsize > MAXPHYS) { + G_RAID3_DEBUG(0, "The blocksize is too big."); + return (EINVAL); + } return (0); } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" Author: ae Date: Tue Feb 1 09:27:28 2011 New Revision: 218162 URL: http://svn.freebsd.org/changeset/base/218162 Log: MFC r217531: Limit maximum number of GPT entries to 4k. It is most realistic value and can prevent kernel memory exhausting when big value is specified from command line. Split reading and writing operation to several iterations to do not trigger KASSERT when data length is greater than MAXPHYS. PR: kern/144962, kern/147851 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) Modified: stable/8/sys/geom/part/g_part_gpt.c ============================================================================== --- stable/8/sys/geom/part/g_part_gpt.c Tue Feb 1 09:27:24 2011 (r218161) +++ stable/8/sys/geom/part/g_part_gpt.c Tue Feb 1 09:27:28 2011 (r218162) @@ -134,7 +134,7 @@ static struct g_part_scheme g_part_gpt_s sizeof(struct g_part_gpt_table), .gps_entrysz = sizeof(struct g_part_gpt_entry), .gps_minent = 128, - .gps_maxent = INT_MAX, + .gps_maxent = 4096, .gps_bootcodesz = MBRSIZE, }; G_PART_SCHEME_DECLARE(g_part_gpt); @@ -317,7 +317,7 @@ gpt_read_tbl(struct g_part_gpt_table *ta struct g_provider *pp; struct gpt_ent *ent, *tbl; char *buf, *p; - unsigned int idx, sectors, tblsz; + unsigned int idx, sectors, tblsz, size; int error; if (hdr == NULL) @@ -329,11 +329,19 @@ gpt_read_tbl(struct g_part_gpt_table *ta table->state[elt] = GPT_STATE_MISSING; tblsz = hdr->hdr_entries * hdr->hdr_entsz; sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize; - buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, - sectors * pp->sectorsize, &error); - if (buf == NULL) - return (NULL); - + buf = g_malloc(sectors * pp->sectorsize, M_WAITOK | M_ZERO); + for (idx = 0; idx < sectors; idx += MAXPHYS / pp->sectorsize) { + size = (sectors - idx > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (sectors - idx) * pp->sectorsize; + p = g_read_data(cp, (table->lba[elt] + idx) * pp->sectorsize, + size, &error); + if (p == NULL) { + g_free(buf); + return (NULL); + } + bcopy(p, buf + idx * pp->sectorsize, size); + g_free(p); + } table->state[elt] = GPT_STATE_CORRUPT; if (crc32(buf, tblsz) != hdr->hdr_crc_table) { g_free(buf); @@ -986,10 +994,15 @@ g_part_gpt_write(struct g_part_table *ba crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); - error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize, - buf + pp->sectorsize, tblsz * pp->sectorsize); - if (error) - goto out; + for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) { + error = g_write_data(cp, + (table->lba[GPT_ELT_PRITBL] + index) * pp->sectorsize, + buf + (index + 1) * pp->sectorsize, + (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (tblsz - index) * pp->sectorsize); + if (error) + goto out; + } error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize, buf, pp->sectorsize); if (error) @@ -1003,10 +1016,15 @@ g_part_gpt_write(struct g_part_table *ba crc = crc32(buf, table->hdr->hdr_size); le32enc(buf + 16, crc); - error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize, - buf + pp->sectorsize, tblsz * pp->sectorsize); - if (error) - goto out; + for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) { + error = g_write_data(cp, + (table->lba[GPT_ELT_SECTBL] + index) * pp->sectorsize, + buf + (index + 1) * pp->sectorsize, + (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS: + (tblsz - index) * pp->sectorsize); + if (error) + goto out; + } error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize, buf, pp->sectorsize); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org" State Changed From-To: patched->closed Fix commited to head/ and stable/8. |