diff --git a/sys/net/ipfw3_layer2/ip_fw3_layer2.c b/sys/net/ipfw3_layer2/ip_fw3_layer2.c index 0000000..1111111 100644 --- a/sys/net/ipfw3_layer2/ip_fw3_layer2.c +++ b/sys/net/ipfw3_layer2/ip_fw3_layer2.c @@ -115,12 +115,21 @@ struct radix_node_head *rnh; struct table_mac_entry *ent = NULL; + *cmd_ctl = IP_FW_CTL_NO; + *cmd_val = IP_FW_NOT_MATCH; + /* DF-0749: cmd->arg1 comes from userland (mac-from table N parser, + lib/libipfw3/layer2/ipfw3_layer2.c:153) with no validation. The + table_ctx array has only IPFW_TABLES_MAX (32) entries; an out-of- + range id drives an OOB read of table_ctx->node here. */ + if (cmd->arg1 >= IPFW_TABLES_MAX) + return; + table_ctx = ctx->table_ctx; table_ctx += cmd->arg1; rnh = table_ctx->node; - *cmd_ctl = IP_FW_CTL_NO; - *cmd_val = IP_FW_NOT_MATCH; + if (table_ctx->type == 0 || rnh == NULL) + return; if ((*args)->eh != NULL) { struct sockaddr sa; sa.sa_len = 8; @@ -158,12 +167,18 @@ struct radix_node_head *rnh; struct table_mac_entry *ent = NULL; + *cmd_ctl = IP_FW_CTL_NO; + *cmd_val = IP_FW_NOT_MATCH; + /* DF-0749: same bounds check as check_mac_from_lookup. */ + if (cmd->arg1 >= IPFW_TABLES_MAX) + return; + table_ctx = ctx->table_ctx; table_ctx += cmd->arg1; rnh = table_ctx->node; - *cmd_ctl = IP_FW_CTL_NO; - *cmd_val = IP_FW_NOT_MATCH; + if (table_ctx->type == 0 || rnh == NULL) + return; if ((*args)->eh != NULL) { struct sockaddr sa; sa.sa_len = 8;