Bug 208035

Summary: IPFW firewall heap overflow
Product: Base System Reporter: CTurt <ecturt>
Component: kernAssignee: freebsd-ipfw (Nobody) <ipfw>
Status: New ---    
Severity: Affects Only Me CC: ae, emaste, melifaro, op, secteam, shawn.webb, thj
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   

Description CTurt 2016-03-15 17:50:01 UTC
There is a heap overflow, triggerable as root only in the IPFW firewall handling code.

sys/netpfil/ipfw/ip_fw_nat.c:

static int
ipfw_nat_cfg(struct sockopt *sopt)
{
	struct cfg_nat_legacy *cfg;
	struct nat44_cfg_nat *ucfg;
	struct cfg_redir_legacy *rdir;
	struct nat44_cfg_redir *urdir;
	char *buf;
	size_t len, len2;
	int error, i;

	len = sopt->sopt_valsize;
	len2 = len + 128;

	/*
	 * Allocate 2x buffer to store converted structures.
	 * new redir_cfg has shrinked, so we're sure that
	 * new buffer size is enough.
	 */
	buf = malloc(roundup2(len, 8) + len2, M_TEMP, M_WAITOK | M_ZERO);
	error = sooptcopyin(sopt, buf, len, sizeof(struct cfg_nat_legacy));

The size calculation passed to `malloc` can be overflown, resulting in heap overflow on `sooptcopyin`.

This function is called when the `IP_FW_NAT_CFG` command is passed to `ipfw_ctl`:

int
ipfw_ctl(struct sockopt *sopt)
{
	...

	/* Save original valsize before it is altered via sooptcopyin() */
	valsize = sopt->sopt_valsize;
	opt = sopt->sopt_name;

	...

	switch (opt) {
		...
case IP_FW_NAT_CFG:
		if (IPFW_NAT_LOADED)
			error = ipfw_nat_cfg_ptr(sopt);
		else {
			printf("IP_FW_NAT_CFG: %s\n",
			    "ipfw_nat not present, please load it");
			error = EINVAL;
		}
		break;

`ipfw_ctl` is only called by `ipfw_ctl3`, which is available only to root processes (must have `PRIV_NETINET_IPFW` privilege):

int
ipfw_ctl3(struct sockopt *sopt)
{
	...

	error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
	if (error != 0)
		return (error);

	if (sopt->sopt_name != IP_FW3)
		return (ipfw_ctl(sopt));
Comment 1 Andrey V. Elsukov freebsd_committer freebsd_triage 2016-05-16 14:08:33 UTC
This code looks like left for compatibility with old binaries. Probably it can be completely removed.