kern/179901: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Fri Jul 12 19:00:01 UTC 2013


The following reply was made to PR kern/179901; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: kern/179901: commit references a PR
Date: Fri, 12 Jul 2013 18:54:56 +0000 (UTC)

 Author: trociny
 Date: Fri Jul 12 18:54:47 2013
 New Revision: 253281
 URL: http://svnweb.freebsd.org/changeset/base/253281
 
 Log:
   MFC r252710:
   
   In r227207, to fix the issue with possible NULL inp_socket pointer
   dereferencing, when checking for SO_REUSEPORT option (and SO_REUSEADDR
   for multicast), INP_REUSEPORT flag was introduced to cache the socket
   option.  It was decided then that one flag would be enough to cache
   both SO_REUSEPORT and SO_REUSEADDR: when processing SO_REUSEADDR
   setsockopt(2), it was checked if it was called for a multicast address
   and INP_REUSEPORT was set accordingly.
   
   Unfortunately that approach does not work when setsockopt(2) is called
   before binding to a multicast address: the multicast check fails and
   INP_REUSEPORT is not set.
   
   Fix this by adding INP_REUSEADDR flag to unconditionally cache
   SO_REUSEADDR.
   
   PR:		179901
   Submitted by:	Michael Gmelin freebsd grem.de (initial version)
   Reviewed by:	rwatson
   Approved by:	re (kib)
 
 Modified:
   stable/9/sys/netinet/in_pcb.c
   stable/9/sys/netinet/in_pcb.h
   stable/9/sys/netinet/ip_output.c
   stable/9/sys/netinet6/in6_pcb.c
   stable/9/sys/netinet6/ip6_output.c
 Directory Properties:
   stable/9/sys/   (props changed)
 
 Modified: stable/9/sys/netinet/in_pcb.c
 ==============================================================================
 --- stable/9/sys/netinet/in_pcb.c	Fri Jul 12 18:52:33 2013	(r253280)
 +++ stable/9/sys/netinet/in_pcb.c	Fri Jul 12 18:54:47 2013	(r253281)
 @@ -466,6 +466,23 @@ in_pcb_lport(struct inpcb *inp, struct i
  
  	return (0);
  }
 +
 +/*
 + * Return cached socket options.
 + */
 +short
 +inp_so_options(const struct inpcb *inp)
 +{
 +   short so_options;
 +
 +   so_options = 0;
 +
 +   if ((inp->inp_flags2 & INP_REUSEPORT) != 0)
 +	   so_options |= SO_REUSEPORT;
 +   if ((inp->inp_flags2 & INP_REUSEADDR) != 0)
 +	   so_options |= SO_REUSEADDR;
 +   return (so_options);
 +}
  #endif /* INET || INET6 */
  
  #ifdef INET
 @@ -594,8 +611,7 @@ in_pcbbind_setup(struct inpcb *inp, stru
  				if (tw == NULL ||
  				    (reuseport & tw->tw_so_options) == 0)
  					return (EADDRINUSE);
 -			} else if (t && (reuseport == 0 ||
 -			    (t->inp_flags2 & INP_REUSEPORT) == 0)) {
 +			} else if (t && (reuseport & inp_so_options(t)) == 0) {
  #ifdef INET6
  				if (ntohl(sin->sin_addr.s_addr) !=
  				    INADDR_ANY ||
 
 Modified: stable/9/sys/netinet/in_pcb.h
 ==============================================================================
 --- stable/9/sys/netinet/in_pcb.h	Fri Jul 12 18:52:33 2013	(r253280)
 +++ stable/9/sys/netinet/in_pcb.h	Fri Jul 12 18:54:47 2013	(r253281)
 @@ -442,6 +442,7 @@ struct tcpcb *
  	inp_inpcbtotcpcb(struct inpcb *inp);
  void 	inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
  		uint32_t *faddr, uint16_t *fp);
 +short	inp_so_options(const struct inpcb *inp);
  
  #endif /* _KERNEL */
  
 @@ -543,6 +544,7 @@ void 	inp_4tuple_get(struct inpcb *inp, 
  #define	INP_PCBGROUPWILD	0x00000004 /* in pcbgroup wildcard list */
  #define	INP_REUSEPORT		0x00000008 /* SO_REUSEPORT option is set */
  #define	INP_FREED		0x00000010 /* inp itself is not valid */
 +#define	INP_REUSEADDR		0x00000020 /* SO_REUSEADDR option is set */
  
  /*
   * Flags passed to in_pcblookup*() functions.
 
 Modified: stable/9/sys/netinet/ip_output.c
 ==============================================================================
 --- stable/9/sys/netinet/ip_output.c	Fri Jul 12 18:52:33 2013	(r253280)
 +++ stable/9/sys/netinet/ip_output.c	Fri Jul 12 18:54:47 2013	(r253281)
 @@ -899,13 +899,10 @@ ip_ctloutput(struct socket *so, struct s
  			switch (sopt->sopt_name) {
  			case SO_REUSEADDR:
  				INP_WLOCK(inp);
 -				if (IN_MULTICAST(ntohl(inp->inp_laddr.s_addr))) {
 -					if ((so->so_options &
 -					    (SO_REUSEADDR | SO_REUSEPORT)) != 0)
 -						inp->inp_flags2 |= INP_REUSEPORT;
 -					else
 -						inp->inp_flags2 &= ~INP_REUSEPORT;
 -				}
 +				if ((so->so_options & SO_REUSEADDR) != 0)
 +					inp->inp_flags2 |= INP_REUSEADDR;
 +				else
 +					inp->inp_flags2 &= ~INP_REUSEADDR;
  				INP_WUNLOCK(inp);
  				error = 0;
  				break;
 
 Modified: stable/9/sys/netinet6/in6_pcb.c
 ==============================================================================
 --- stable/9/sys/netinet6/in6_pcb.c	Fri Jul 12 18:52:33 2013	(r253280)
 +++ stable/9/sys/netinet6/in6_pcb.c	Fri Jul 12 18:54:47 2013	(r253281)
 @@ -245,8 +245,7 @@ in6_pcbbind(register struct inpcb *inp, 
  				if (tw == NULL ||
  				    (reuseport & tw->tw_so_options) == 0)
  					return (EADDRINUSE);
 -			} else if (t && (reuseport == 0 ||
 -			    (t->inp_flags2 & INP_REUSEPORT) == 0)) {
 +			} else if (t && (reuseport & inp_so_options(t)) == 0) {
  				return (EADDRINUSE);
  			}
  #ifdef INET
 @@ -267,8 +266,8 @@ in6_pcbbind(register struct inpcb *inp, 
  					     INP_IPV6PROTO) ==
  					     (t->inp_vflag & INP_IPV6PROTO))))
  						return (EADDRINUSE);
 -				} else if (t && (reuseport == 0 ||
 -				    (t->inp_flags2 & INP_REUSEPORT) == 0) &&
 +				} else if (t &&
 +				    (reuseport & inp_so_options(t)) == 0 &&
  				    (ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
  				    (t->inp_vflag & INP_IPV6PROTO) != 0))
  					return (EADDRINUSE);
 
 Modified: stable/9/sys/netinet6/ip6_output.c
 ==============================================================================
 --- stable/9/sys/netinet6/ip6_output.c	Fri Jul 12 18:52:33 2013	(r253280)
 +++ stable/9/sys/netinet6/ip6_output.c	Fri Jul 12 18:54:47 2013	(r253281)
 @@ -1491,13 +1491,10 @@ ip6_ctloutput(struct socket *so, struct 
  			switch (sopt->sopt_name) {
  			case SO_REUSEADDR:
  				INP_WLOCK(in6p);
 -				if (IN_MULTICAST(ntohl(in6p->inp_laddr.s_addr))) {
 -					if ((so->so_options &
 -					    (SO_REUSEADDR | SO_REUSEPORT)) != 0)
 -						in6p->inp_flags2 |= INP_REUSEPORT;
 -					else
 -						in6p->inp_flags2 &= ~INP_REUSEPORT;
 -				}
 +				if ((so->so_options & SO_REUSEADDR) != 0)
 +					in6p->inp_flags2 |= INP_REUSEADDR;
 +				else
 +					in6p->inp_flags2 &= ~INP_REUSEADDR;
  				INP_WUNLOCK(in6p);
  				error = 0;
  				break;
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-net mailing list