DF-3439 / fix.diff
--- a/sys/net/ipfw3/ip_fw3.c +++ b/sys/net/ipfw3/ip_fw3.c @@ -825,11 +825,24 @@ { struct netmsg_del *dmsg = (struct netmsg_del *)nmsg; struct ipfw3_context *ctx = fw3_ctx[mycpuid]; - struct ip_fw *rule, *prev = NULL; + struct ip_fw *rule, *prev = NULL, *walk; rule = ctx->rules; while (rule!=NULL) { if (rule->rulenum == dmsg->rulenum) { + /* + * Rules that skip forward (skipto) cache the + * pointer to their target rule in ->next_rule + * (lookup_next_rule via check_skipto). + * Invalidate every cached pointer targeting the + * rule we are about to free so packet matching + * can never follow a dangling next_rule into + * freed memory (DF-3439). + */ + for (walk = ctx->rules; walk; walk = walk->next) { + if (walk->next_rule == rule) + walk->next_rule = NULL; + } ip_fw3_delete_rule(ctx, prev, rule); break; } |