DragonFlyBSD Kernel Audit
DF-0472 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/ipfw3/ip_fw3.c b/sys/net/ipfw3/ip_fw3.c
--- a/sys/net/ipfw3/ip_fw3.c
+++ b/sys/net/ipfw3/ip_fw3.c
@@ -964,6 +964,24 @@
 	}
 	ioc_rule = sopt->sopt_val;
 
+	/*
+	 * Validate cmd_len / act_ofs against the data actually supplied.
+	 * Without this a caller may set cmd_len=255 while sending only a
+	 * few instruction words: krealloc() grows the buffer to 1020 bytes
+	 * (uninitialised tail) and add_rule_dispatch() then bcopy()s
+	 * cmd_len*4 bytes out of ioc_rule->cmd, over-reading ~36 bytes past
+	 * the allocation and copying uninitialised heap into the rule.  That
+	 * garbage is leaked back to userland via IP_FW_GET and is also used
+	 * as the filter_funcs[module][opcode] indices by ip_fw3_chk, yielding
+	 * an out-of-bounds indirect function call.
+	 */
+	if (ioc_rule->cmd_len > IPFW_RULE_SIZE_MAX -
+			((sizeof(*ioc_rule) - sizeof(ipfw_insn)) / sizeof(uint32_t)) ||
+	    ioc_rule->act_ofs >= ioc_rule->cmd_len ||
+	    size < IOC_RULESIZE(ioc_rule)) {
+		return EINVAL;
+	}
+
 	ip_fw3_add_rule(ioc_rule);
 	return 0;
 }