geom_part: Check number of GPT entries and size of GPT entry

Current specification does not have upper limit of the number of
partition entries and the size of partition entry. In
799eac8c3d Andrey V. Elsukov introduced a
limit maximum number of GPT entries to 4k, but that is for write routine
(gpart create) only. When attaching disks that have large number of GPT
entries exceeding the limit, or disks with large size of partition
entry, it is still possible to exhaust kernel memory.

1. Reuse the limit of the maximum number of partition entries.
2. Limit the maximum size of GPT entry to 1k.

In current specification (2.10) the size of GPT entry is 128 *
2^n while n >= 0, and the size - 128 is reserved. 1k should be
sufficient enough for foreseen future.

PR:		266548
Discussed with:	imp
Reviewed by:	markj
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D36717
This commit is contained in:
Zhenlei Huang 2022-10-18 11:03:02 -04:00 committed by Mark Johnston
parent 3467e28f3d
commit 5be5d0d5cb

View file

@ -85,6 +85,7 @@ enum gpt_state {
GPT_STATE_MISSING, /* No signature found. */
GPT_STATE_CORRUPT, /* Checksum mismatch. */
GPT_STATE_INVALID, /* Nonconformant/invalid. */
GPT_STATE_UNSUPPORTED, /* Not supported. */
GPT_STATE_OK /* Perfectly fine. */
};
@ -148,6 +149,8 @@ static kobj_method_t g_part_gpt_methods[] = {
{ 0, 0 }
};
#define MAXENTSIZE 1024
static struct g_part_scheme g_part_gpt_scheme = {
"GPT",
g_part_gpt_methods,
@ -548,6 +551,11 @@ gpt_read_tbl(struct g_part_gpt_table *table, struct g_consumer *cp,
if (hdr == NULL)
return (NULL);
if (hdr->hdr_entries > g_part_gpt_scheme.gps_maxent ||
hdr->hdr_entsz > MAXENTSIZE) {
table->state[elt] = GPT_STATE_UNSUPPORTED;
return (NULL);
}
pp = cp->provider;
table->lba[elt] = hdr->hdr_lba_table;
@ -961,10 +969,25 @@ g_part_gpt_read(struct g_part_table *basetable, struct g_consumer *cp)
/* Fail if we haven't got any good tables at all. */
if (table->state[GPT_ELT_PRITBL] != GPT_STATE_OK &&
table->state[GPT_ELT_SECTBL] != GPT_STATE_OK) {
printf("GEOM: %s: corrupt or invalid GPT detected.\n",
pp->name);
printf("GEOM: %s: GPT rejected -- may not be recoverable.\n",
pp->name);
if (table->state[GPT_ELT_PRITBL] == GPT_STATE_UNSUPPORTED &&
table->state[GPT_ELT_SECTBL] == GPT_STATE_UNSUPPORTED &&
gpt_matched_hdrs(prihdr, sechdr)) {
printf("GEOM: %s: unsupported GPT detected.\n",
pp->name);
printf(
"GEOM: %s: number of GPT entries: %u, entry size: %uB.\n",
pp->name, prihdr->hdr_entries, prihdr->hdr_entsz);
printf(
"GEOM: %s: maximum supported number of GPT entries: %u, entry size: %uB.\n",
pp->name, g_part_gpt_scheme.gps_maxent, MAXENTSIZE);
printf("GEOM: %s: GPT rejected.\n", pp->name);
} else {
printf("GEOM: %s: corrupt or invalid GPT detected.\n",
pp->name);
printf(
"GEOM: %s: GPT rejected -- may not be recoverable.\n",
pp->name);
}
if (prihdr != NULL)
g_free(prihdr);
if (pritbl != NULL)