Subject: crashes in ipfilter on i386
To: None <tech-net@netbsd.org>
From: Greg Troxel <gdt@ir.bbn.com>
List: tech-net
Date: 07/24/2007 10:46:56
I have an i386 running netbsd-4, and it's been crashing ever since I
upgraded recently.  It is on an ethernet with v6 activity.  I am getting
dumps for which I can't get useful backtraces, but dmesg -M shows the
fault address.

It's in frpr_icmp6, in fil.c, and it's the access to the 4th word of the
v6 src header (see the second line of IP6_NEQ call).  (gcc puts the 4th
word first, then 3, 2, 1)

		switch (icmp6->icmp6_type)
		{
		case ICMP6_ECHO_REPLY :
		case ICMP6_ECHO_REQUEST :
			minicmpsz = ICMP6ERR_MINPKTLEN - sizeof(ip6_t);
			break;
		case ICMP6_DST_UNREACH :
		case ICMP6_PACKET_TOO_BIG :
		case ICMP6_TIME_EXCEEDED :
		case ICMP6_PARAM_PROB :
			fin->fin_flx |= FI_ICMPERR;
			if ((fin->fin_m != NULL) &&
			    (M_LEN(fin->fin_m) < fin->fin_plen)) {
				if (fr_coalesce(fin) != 1)
					return;
			}

			if (frpr_pullup(fin, ICMP6ERR_MINPKTLEN) == -1)
				return;

			/*
			 * If the destination of this packet doesn't match the
			 * source of the original packet then this packet is
			 * not correct.
			 */
			icmp6 = fin->fin_dp;
			ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN);
			if (IP6_NEQ(&fin->fin_fi.fi_dst,
				    &ip6->ip6_src))
				fin->fin_flx |= FI_BAD;

			minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t);
			break;
		default :
			break;
		}


ICMP6ERR_MINPKTLEN is 8+40
ICMPERR_ICMPHLEN is 8
ICMP6ERR_IPICMPHLEN is (40 + 8 + 40)

It seems at least odd to be using ICMPERR_ICMPHLEN with v6, but that
doesn't seem to be an issue.

Is the frpr_pullup ensuring that there is the outer IPv6 header, plus
the 8 bytes of icmp header, plus the whole source address from the
contained packet?  I don't understand the rules about fin_dp - it seems
to be usd for alignment, and frpr_pullup seems to be be missing the
outer v6 header in the pullup amount.