svn commit: r336301 - head/sys/netinet6

Matt Macy mmacy at FreeBSD.org
Sun Jul 15 00:47:08 UTC 2018


Author: mmacy
Date: Sun Jul 15 00:47:06 2018
New Revision: 336301
URL: https://svnweb.freebsd.org/changeset/base/336301

Log:
  acquire inp lock around ip6_pcbopt to fix IPV6_TCLASS panic
  
  Simple fix to address panics relating to setting IPV6_TCLASS
  with setsockopt(). The premise of this change is that it is
  ok to call malloc with M_NOWAIT while holding a lock on the
  in6p.
  
  If it later turns out that it is not ok, then major surgery
  will be required, as ip6_setpktopt() will have to be fixed
  (as it also calls malloc with M_NOWAIT) which pulls in the
  ip6_pcbopts(), ip6_setpktopts(), ip6_setpktopt() call chain.
  
  Submitted by:	Jason Eggnet
  Reviewed by:	rrs, transport, sbruno
  Sponsored by:	Limelight Networks
  Differential Revision:	https://reviews.freebsd.org/D16201

Modified:
  head/sys/netinet6/ip6_output.c

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c	Sun Jul 15 00:31:17 2018	(r336300)
+++ head/sys/netinet6/ip6_output.c	Sun Jul 15 00:47:06 2018	(r336301)
@@ -1636,11 +1636,17 @@ do {									\
 						error = EINVAL;
 						break;
 					}
+					INP_WLOCK(in6p);
+					if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+						INP_WUNLOCK(in6p);
+						return (ECONNRESET);
+					}
 					optp = &in6p->in6p_outputopts;
 					error = ip6_pcbopt(IPV6_HOPLIMIT,
 					    (u_char *)&optval, sizeof(optval),
 					    optp, (td != NULL) ? td->td_ucred :
 					    NULL, uproto);
+					INP_WUNLOCK(in6p);
 					break;
 				}
 
@@ -1750,11 +1756,17 @@ do {									\
 					break;
 				{
 					struct ip6_pktopts **optp;
+					INP_WLOCK(in6p);
+					if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+						INP_WUNLOCK(in6p);
+						return (ECONNRESET);
+					}
 					optp = &in6p->in6p_outputopts;
 					error = ip6_pcbopt(optname,
 					    (u_char *)&optval, sizeof(optval),
 					    optp, (td != NULL) ? td->td_ucred :
 					    NULL, uproto);
+					INP_WUNLOCK(in6p);
 					break;
 				}
 
@@ -1836,10 +1848,16 @@ do {									\
 					break;
 				optlen = sopt->sopt_valsize;
 				optbuf = optbuf_storage;
+				INP_WLOCK(in6p);
+				if (in6p->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
+					INP_WUNLOCK(in6p);
+					return (ECONNRESET);
+				}
 				optp = &in6p->in6p_outputopts;
 				error = ip6_pcbopt(optname, optbuf, optlen,
 				    optp, (td != NULL) ? td->td_ucred : NULL,
 				    uproto);
+				INP_WUNLOCK(in6p);
 				break;
 			}
 #undef OPTSET
@@ -2286,7 +2304,9 @@ ip6_pcbopt(int optname, u_char *buf, int len, struct i
 
 	if (*pktopt == NULL) {
 		*pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
-		    M_WAITOK);
+		    M_NOWAIT);
+		if (*pktopt == NULL)
+			return (ENOBUFS);
 		ip6_initpktopts(*pktopt);
 	}
 	opt = *pktopt;


More information about the svn-src-all mailing list