Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 May 2010 04:50:03 GMT
From:      Matthew Luckie <mjl@luckie.org.nz>
To:        freebsd-ipfw@FreeBSD.org
Subject:   Re: kern/145733: [patch] ipfw flaws with ipv6 fragments
Message-ID:  <201005080450.o484o3wN077562@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/145733; it has been noted by GNATS.

From: Matthew Luckie <mjl@luckie.org.nz>
To: freebsd-bugs@FreeBSD.org
Cc:  
Subject: Re: kern/145733: [patch] ipfw flaws with ipv6 fragments
Date: Sat, 8 May 2010 09:24:23 +1200

 --xHFwDpU9dbj6ez1V
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Attached is a revised patch fixing a third flaw.  ipfw will reject
 very small IPv6 fragments when it tries to pullup the transport
 header.  This relaxes the code to be consistent with the IPv4 path
 where it only tries to pull up the transport header on fragments with
 offset zero.
 --xHFwDpU9dbj6ez1V
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename=patch-ipfw-fraghdr
 
 --- ip_fw2.c.orig	2010-05-08 08:38:40.000000000 +1200
 +++ ip_fw2.c	2010-05-08 09:10:28.000000000 +1200
 @@ -804,6 +804,7 @@
  	char *action;
  	int limit_reached = 0;
  	char action2[40], proto[128], fragment[32];
 +	u_short mf = 0;
  
  	fragment[0] = '\0';
  	proto[0] = '\0';
 @@ -952,6 +953,8 @@
  			snprintf(dst, sizeof(dst), "[%s]",
  			    ip6_sprintf(ip6buf, &args->f_id.dst_ip6));
  
 +			mf = offset & IP6F_MORE_FRAG;
 +			offset &= IP6F_OFF_MASK;
  			ip6 = (struct ip6_hdr *)ip;
  			tcp = (struct tcphdr *)(((char *)ip) + hlen);
  			udp = (struct udphdr *)(((char *)ip) + hlen);
 @@ -1021,13 +1024,13 @@
  
  #ifdef INET6
  		if (IS_IP6_FLOW_ID(&(args->f_id))) {
 -			if (offset & (IP6F_OFF_MASK | IP6F_MORE_FRAG))
 +			if (offset || mf)
  				snprintf(SNPARGS(fragment, 0),
  				    " (frag %08x:%d@%d%s)",
  				    args->f_id.frag_id6,
  				    ntohs(ip6->ip6_plen) - hlen,
 -				    ntohs(offset & IP6F_OFF_MASK) << 3,
 -				    (offset & IP6F_MORE_FRAG) ? "+" : "");
 +				    ntohs(offset) << 3,
 +				    mf ? "+" : "");
  		} else
  #endif
  		{
 @@ -2184,16 +2187,13 @@
  
  	/*
  	 * offset	The offset of a fragment. offset != 0 means that
 -	 *	we have a fragment at this offset of an IPv4 packet.
 -	 *	offset == 0 means that (if this is an IPv4 packet)
 -	 *	this is the first or only fragment.
 -	 *	For IPv6 offset == 0 means there is no Fragment Header. 
 -	 *	If offset != 0 for IPv6 always use correct mask to
 -	 *	get the correct offset because we add IP6F_MORE_FRAG
 -	 *	to be able to dectect the first fragment which would
 -	 *	otherwise have offset = 0.
 +	 *	we have a fragment at this offset.
 +	 *	offset == 0 means that this is the first or only fragment.
 +	 *
 +	 * mf		The MF bit masked out of IPv6 packets.
  	 */
  	u_short offset = 0;
 +	u_short mf = 0;
  
  	/*
  	 * Local copies of addresses. They are only valid if we have
 @@ -2281,7 +2281,7 @@
  		proto = ip6->ip6_nxt;
  
  		/* Search extension headers to find upper layer protocols */
 -		while (ulp == NULL) {
 +		while (ulp == NULL && offset == 0) {
  			switch (proto) {
  			case IPPROTO_ICMPV6:
  				PULLUP_TO(hlen, ulp, struct icmp6_hdr);
 @@ -2345,17 +2345,8 @@
  				proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
  				offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
  					IP6F_OFF_MASK;
 -				/* Add IP6F_MORE_FRAG for offset of first
 -				 * fragment to be != 0. */
 -				offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
 +				mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
  					IP6F_MORE_FRAG;
 -				if (offset == 0) {
 -					printf("IPFW2: IPV6 - Invalid Fragment "
 -					    "Header\n");
 -					if (V_fw_deny_unknown_exthdrs)
 -					    return (IP_FW_DENY);
 -					break;
 -				}
  				args->f_id.frag_id6 =
  				    ntohl(((struct ip6_frag *)ulp)->ip6f_ident);
  				ulp = NULL;
 @@ -2941,7 +2932,7 @@
  			case O_LOG:
  				if (V_fw_verbose)
  					ipfw_log(f, hlen, args, m,
 -					    oif, offset, tablearg, ip);
 +					    oif, offset|mf, tablearg, ip);
  				match = 1;
  				break;
  
 
 --xHFwDpU9dbj6ez1V--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005080450.o484o3wN077562>