Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Jan 2000 03:48:01 -0800
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        Warner Losh <imp@village.org>
Cc:        security@FreeBSD.ORG
Subject:   Re: stream.c worst-case kernel paths
Message-ID:  <200001221148.DAA16946@salsa.gv.tsc.tdk.com>
In-Reply-To: <200001220659.WAA15977@salsa.gv.tsc.tdk.com>
References:   <200001220659.WAA15977@salsa.gv.tsc.tdk.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Jan 21, 10:59pm, Don Lewis wrote:
} Subject: Re: stream.c worst-case kernel paths
} On Jan 21, 11:09pm, Warner Losh wrote:
} } Subject: Re: stream.c worst-case kernel paths
} } In message <200001220551.VAA15775@salsa.gv.tsc.tdk.com> Don Lewis writes:
} } : (b) still needs to be generalized to cover other paths that generate
} } : RST packets.
} } 
} } Matt has a patch for (b).
} 
} Which is why I didn't implement (b).  I figured his implementation
} would be better than mine.
} 
} } You two might want to merge the two.
} 
} That sounds good to me.

Ok, I haven't seen Matt's patch for (b), so I just moved the exiting
ICMP_BANDLIM code down to the dropwithreset code.  I also made the
part of optimization to the wildcard test that Brett and I discussed.

This patch compiled OK for me , and function correctly when I did some
simple testing.  Now it really needs a good thrashing.


*** tcp_input.c.orig	Fri Jan 21 09:04:37 2000
--- tcp_input.c	Sat Jan 22 03:40:05 2000
***************
*** 381,386 ****
--- 381,387 ----
  	struct tcpopt to;		/* options in this segment */
  	struct rmxp_tao *taop;		/* pointer to our TAO cache entry */
  	struct rmxp_tao	tao_noncached;	/* in case there's no cached entry */
+ 	int wildcard = 0;
  #ifdef TCPDEBUG
  	short ostate = 0;
  #endif
***************
*** 511,518 ****
  	drop_hdrlen = off0 + off;
  
  	/*
! 	 * Locate pcb for segment.
  	 */
  findpcb:
  #ifdef IPFIREWALL_FORWARD
  	if (ip_fw_fwd_addr != NULL
--- 512,528 ----
  	drop_hdrlen = off0 + off;
  
  	/*
! 	 * Locate pcb for segment.  If this is not a SYN segment, don't
! 	 * bother searching for the pcb of a listening socket with a
! 	 * wildcard address.
! 	 *
! 	 * Checking TH_RST isn't strictly necessary here, but it doesn't
! 	 * cost anything, saves a hash lookup, takes a shorter path to
! 	 * dropwithreset (which will drop the packet), and allows a test
! 	 * to be removed from the TCPS_LISTEN case.
  	 */
+ 	if ((thflags & (TH_ACK|TH_SYN|TH_RST)) == TH_SYN)
+ 		wildcard = 1;
  findpcb:
  #ifdef IPFIREWALL_FORWARD
  	if (ip_fw_fwd_addr != NULL
***************
*** 533,544 ****
  			if (!ip_fw_fwd_addr->sin_port) {
  				inp = in_pcblookup_hash(&tcbinfo, ip->ip_src,
  				    th->th_sport, ip_fw_fwd_addr->sin_addr,
! 				    th->th_dport, 1, m->m_pkthdr.rcvif);
  			} else {
  				inp = in_pcblookup_hash(&tcbinfo,
  				    ip->ip_src, th->th_sport,
  	    			    ip_fw_fwd_addr->sin_addr,
! 				    ntohs(ip_fw_fwd_addr->sin_port), 1,
  				    m->m_pkthdr.rcvif);
  			}
  		}
--- 543,554 ----
  			if (!ip_fw_fwd_addr->sin_port) {
  				inp = in_pcblookup_hash(&tcbinfo, ip->ip_src,
  				    th->th_sport, ip_fw_fwd_addr->sin_addr,
! 				    th->th_dport, wildcard, m->m_pkthdr.rcvif);
  			} else {
  				inp = in_pcblookup_hash(&tcbinfo,
  				    ip->ip_src, th->th_sport,
  	    			    ip_fw_fwd_addr->sin_addr,
! 				    ntohs(ip_fw_fwd_addr->sin_port), wildcard,
  				    m->m_pkthdr.rcvif);
  			}
  		}
***************
*** 549,560 ****
  #ifdef INET6
  	if (isipv6)
  		inp = in6_pcblookup_hash(&tcbinfo, &ip6->ip6_src, th->th_sport,
! 					 &ip6->ip6_dst, th->th_dport, 1,
  					 m->m_pkthdr.rcvif);
  	else
  #endif /* INET6 */
  	inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport,
! 	    ip->ip_dst, th->th_dport, 1, m->m_pkthdr.rcvif);
        }
  
  #ifdef IPSEC
--- 559,570 ----
  #ifdef INET6
  	if (isipv6)
  		inp = in6_pcblookup_hash(&tcbinfo, &ip6->ip6_src, th->th_sport,
! 					 &ip6->ip6_dst, th->th_dport, wildcard,
  					 m->m_pkthdr.rcvif);
  	else
  #endif /* INET6 */
  	inp = in_pcblookup_hash(&tcbinfo, ip->ip_src, th->th_sport,
! 	    ip->ip_dst, th->th_dport, wildcard, m->m_pkthdr.rcvif);
        }
  
  #ifdef IPSEC
***************
*** 615,624 ****
  				break;
  			}
  		}
- #ifdef ICMP_BANDLIM
- 		if (badport_bandlim(1) < 0)
- 			goto drop;
- #endif
  		if (blackhole) { 
  			switch (blackhole) {
  			case 1:
--- 625,630 ----
***************
*** 996,1001 ****
--- 1002,1013 ----
  		register struct sockaddr_in6 *sin6;
  #endif
  
+ 		/*
+ 		 * XXX - the following three tests should no longer be
+ 		 * necessary because of the "wildcard" test added
+ 		 * above.  These should probably be changed to assertions
+ 		 * until the code is thoroughly shaked out.
+ 		 */
  		if (thflags & TH_RST)
  			goto drop;
  		if (thflags & TH_ACK)
***************
*** 1017,1032 ****
  		 * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
  		 * in_broadcast() should never return true on a received
  		 * packet with M_BCAST not set.
  		 */
  		if (m->m_flags & (M_BCAST|M_MCAST))
  			goto drop;
  #ifdef INET6
  		if (isipv6) {
! 			if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
  				goto drop;
  		} else
  #endif
! 		if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
  			goto drop;
  #ifdef INET6
  		if (isipv6) {
--- 1029,1050 ----
  		 * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
  		 * in_broadcast() should never return true on a received
  		 * packet with M_BCAST not set.
+ 		 *
+ 		 * Packets with a multicast source address should also
+ 		 * be discarded.
  		 */
  		if (m->m_flags & (M_BCAST|M_MCAST))
  			goto drop;
  #ifdef INET6
  		if (isipv6) {
! 			if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
! 			    IN6_IS_ADDR_MULTICAST(&ip6->ip6_src))
  				goto drop;
  		} else
  #endif
! 		if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
! 		    IN_MULTICAST(ntohl(ip->ip_src.s_addr)) ||
! 		    IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)))
  			goto drop;
  #ifdef INET6
  		if (isipv6) {
***************
*** 2217,2229 ****
  		goto drop;
  #ifdef INET6
  	if (isipv6) {
! 		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
  			goto drop;
  	} else
  #endif /* INET6 */
! 	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
  		goto drop;
  	/* IPv6 anycast check is done at tcp6_input() */
  #ifdef TCPDEBUG
  	if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
  		tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
--- 2235,2254 ----
  		goto drop;
  #ifdef INET6
  	if (isipv6) {
! 		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
! 		    IN6_IS_ADDR_MULTICAST(&ip6->ip6_src))
  			goto drop;
  	} else
  #endif /* INET6 */
! 	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
! 	    IN_MULTICAST(ntohl(ip->ip_src.s_addr)) ||
! 	    IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)))
  		goto drop;
  	/* IPv6 anycast check is done at tcp6_input() */
+ #ifdef ICMP_BANDLIM
+ 	if (badport_bandlim(1) < 0)
+ 		goto drop;
+ #endif
  #ifdef TCPDEBUG
  	if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
  		tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message




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