Author: sbruno
Date: Thu Mar 22 22:29:32 2018
New Revision: 331379
URL: https://svnweb.freebsd.org/changeset/base/331379

Log:
  Simple locking fixes in ip_ctloutput, ip6_ctloutput, rip_ctloutput.
  
  Submitted by: Jason Eggleston <ja...@eggnet.com>
  Sponsored by: Limelight Networks
  Differential Revision:        https://reviews.freebsd.org/D14624

Modified:
  head/sys/netinet/ip_output.c
  head/sys/netinet/raw_ip.c
  head/sys/netinet6/ip6_output.c

Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c        Thu Mar 22 22:13:46 2018        
(r331378)
+++ head/sys/netinet/ip_output.c        Thu Mar 22 22:29:32 2018        
(r331379)
@@ -1314,12 +1314,14 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
                                break;
 
                        case IP_PORTRANGE:
+                               INP_RLOCK(inp);
                                if (inp->inp_flags & INP_HIGHPORT)
                                        optval = IP_PORTRANGE_HIGH;
                                else if (inp->inp_flags & INP_LOWPORT)
                                        optval = IP_PORTRANGE_LOW;
                                else
                                        optval = 0;
+                               INP_RUNLOCK(inp);
                                break;
 
                        case IP_ONESBCAST:
@@ -1345,9 +1347,11 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
                                break;
 #ifdef RSS
                        case IP_RSSBUCKETID:
+                               INP_RLOCK(inp);
                                retval = rss_hash2bucket(inp->inp_flowid,
                                    inp->inp_flowtype,
                                    &rss_bucket);
+                               INP_RUNLOCK(inp);
                                if (retval == 0)
                                        optval = rss_bucket;
                                else

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c   Thu Mar 22 22:13:46 2018        (r331378)
+++ head/sys/netinet/raw_ip.c   Thu Mar 22 22:29:32 2018        (r331379)
@@ -639,10 +639,12 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
                                            sizeof optval);
                        if (error)
                                break;
+                       INP_WLOCK(inp);
                        if (optval)
                                inp->inp_flags |= INP_HDRINCL;
                        else
                                inp->inp_flags &= ~INP_HDRINCL;
+                       INP_WUNLOCK(inp);
                        break;
 
                case IP_FW3:    /* generic ipfw v.3 functions */

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c      Thu Mar 22 22:13:46 2018        
(r331378)
+++ head/sys/netinet6/ip6_output.c      Thu Mar 22 22:29:32 2018        
(r331379)
@@ -1498,8 +1498,10 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
                                error = soopt_mcopyin(sopt, m); /* XXX */
                                if (error != 0)
                                        break;
+                               INP_WLOCK(in6p);
                                error = ip6_pcbopts(&in6p->in6p_outputopts,
                                                    m, so, sopt);
+                               INP_WUNLOCK(in6p);
                                m_freem(m); /* XXX */
                                break;
                        }
@@ -1635,11 +1637,13 @@ do {                                                    
                \
                                                error = EINVAL;
                                                break;
                                        }
+                                       INP_WLOCK(in6p);
                                        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;
                                }
 
@@ -1690,8 +1694,10 @@ do {                                                     
                \
                                         * available only prior to bind(2).
                                         * see ipng mailing list, Jun 22 2001.
                                         */
+                                       INP_WLOCK(in6p);
                                        if (in6p->inp_lport ||
                                            
!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
+                                               INP_WUNLOCK(in6p);
                                                error = EINVAL;
                                                break;
                                        }
@@ -1700,6 +1706,7 @@ do {                                                      
                \
                                                in6p->inp_vflag &= ~INP_IPV4;
                                        else
                                                in6p->inp_vflag |= INP_IPV4;
+                                       INP_WUNLOCK(in6p);
                                        break;
                                case IPV6_RECVTCLASS:
                                        /* cannot mix with RFC2292 XXX */
@@ -1749,11 +1756,13 @@ do {                                                    
                \
                                        break;
                                {
                                        struct ip6_pktopts **optp;
+                                       INP_WLOCK(in6p);
                                        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;
                                }
 
@@ -1818,12 +1827,6 @@ do {                                                     
                \
                                int optlen;
                                struct ip6_pktopts **optp;
 
-                               /* cannot mix with RFC2292 */
-                               if (OPTBIT(IN6P_RFC2292)) {
-                                       error = EINVAL;
-                                       break;
-                               }
-
                                /*
                                 * We only ensure valsize is not too large
                                 * here.  Further validation will be done
@@ -1833,12 +1836,21 @@ do {                                                    
                \
                                    sizeof(optbuf_storage), 0);
                                if (error)
                                        break;
+
+                               INP_WLOCK(in6p);
+                               /* cannot mix with RFC2292 */
+                               if (OPTBIT(IN6P_RFC2292)) {
+                                       INP_WUNLOCK(in6p);
+                                       error = EINVAL;
+                                       break;
+                               }
                                optlen = sopt->sopt_valsize;
                                optbuf = optbuf_storage;
                                optp = &in6p->in6p_outputopts;
                                error = ip6_pcbopt(optname, optbuf, optlen,
                                    optp, (td != NULL) ? td->td_ucred : NULL,
                                    uproto);
+                               INP_WUNLOCK(in6p);
                                break;
                        }
 #undef OPTSET
@@ -2023,10 +2035,12 @@ do {                                                    
                \
                                        break;
 #ifdef RSS
                                case IPV6_RSSBUCKETID:
+                                       INP_RLOCK(in6p);
                                        retval =
                                            rss_hash2bucket(in6p->inp_flowid,
                                            in6p->inp_flowtype,
                                            &rss_bucket);
+                                       INP_RUNLOCK(in6p);
                                        if (retval == 0)
                                                optval = rss_bucket;
                                        else
@@ -2230,6 +2244,8 @@ ip6_pcbopts(struct ip6_pktopts **pktopt, struct mbuf *
        int error = 0;
        struct thread *td = sopt->sopt_td;
 
+       INP_WLOCK_ASSERT(sotoinpcb(so));
+
        /* turn off any old options. */
        if (opt) {
 #ifdef DIAGNOSTIC
@@ -3073,6 +3089,8 @@ int
 ip6_optlen(struct inpcb *in6p)
 {
        int len;
+
+       INP_WLOCK_ASSERT(in6p);
 
        if (!in6p->in6p_outputopts)
                return 0;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to