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
This commit is contained in:
Andrey V. Elsukov 2011-01-18 09:52:53 +00:00
parent 2c4992db70
commit 799eac8c3d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=217531

View file

@ -134,7 +134,7 @@ static struct g_part_scheme g_part_gpt_scheme = {
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 *table, struct g_consumer *cp,
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 *table, struct g_consumer *cp,
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 *basetable, struct g_consumer *cp)
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 *basetable, struct g_consumer *cp)
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);