diff --git a/sys/net/ipfw3_basic/ip_fw3_table.c b/sys/net/ipfw3_basic/ip_fw3_table.c --- a/sys/net/ipfw3_basic/ip_fw3_table.c +++ b/sys/net/ipfw3_basic/ip_fw3_table.c @@ -524,6 +524,21 @@ ip_fw3_ctl_table_sockopt(struct sockopt *sopt) { int error = 0; + /* + * DF-2580: bound-check the table id once, before any dispatch. + * Every table_*_dispatch() does `table_ctx += id' against the + * ctx->table_ctx[IPFW_TABLES_MAX] array with no other check; an + * out-of-range signed id gives a controlled kernel heap OOB + * read/write. LIST iterates all slots and never indexes by id, + * so it is exempt. + */ + if (sopt->sopt_name != IP_FW_TABLE_LIST && + sopt->sopt_valsize >= sizeof(int)) { + struct ipfw_ioc_table *ioc = + (struct ipfw_ioc_table *)sopt->sopt_val; + if (ioc->id < 0 || ioc->id >= IPFW_TABLES_MAX) + return (EINVAL); + } switch (sopt->sopt_name) { case IP_FW_TABLE_CREATE: error = ip_fw3_ctl_table_create(sopt);