On Wed, Sep 13 2017, Martin Pieuchot <[email protected]> wrote:
> On 12/09/17(Tue) 15:53, Martin Pieuchot wrote:
>> Diff below reduces the scope of the NET_LOCK(), this time in sysctl
>> path.  It is interesting for multiple reasons:
>> 
>> - It reduces the contention on the NET_LOCK(), which should improve
>>   the overall latency on the system when counters are frequently
>>   queried.  Accesses to read-only operations and per-CPU counters
>>   are no longer protected by the NET_LOCK().
>> 
>> - It allows per-CPU counters to be accessed in parallel.  counters_read(9)
>>   is now executed without holding the NET_LOCK().
>> 
>> - sysctl_mq() is now MP-safe, by serializing access using the mq's
>>   mutex.  However a dance is required to not hold a mutex around
>>   copyin(9)/copyout(9).
>> 
>> - The NET_LOCK() is now taken around all sysctl_int(), sysctl_struct()
>>   and sysctl_int_arr().  This is not nice but it will allow people to
>>   fix parts of the sysctl path independently.
>> 
>> Note that all data structure currently protected in these sysctl paths
>> do not necessarily need the NET_LOCK().  Take CARP's carp_opts[] for
>> example.  Does it need the NET_LOCK()?  Is it at all the right primitive?
>> Well interested readers can answer with diffs and explanations to these
>> questions :)
>> 
>> Comments, oks?

Looks good to me, ok jca@

> Updated diff fixing two issues spotted by visa@.
>
> Index: kern/uipc_domain.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_domain.c,v
> retrieving revision 1.52
> diff -u -p -r1.52 uipc_domain.c
> --- kern/uipc_domain.c        11 Aug 2017 21:24:19 -0000      1.52
> +++ kern/uipc_domain.c        13 Sep 2017 08:28:27 -0000
> @@ -207,10 +207,8 @@ net_sysctl(int *name, u_int namelen, voi
>       protocol = name[1];
>       for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
>               if (pr->pr_protocol == protocol && pr->pr_sysctl) {
> -                     NET_LOCK();
>                       error = (*pr->pr_sysctl)(name + 2, namelen - 2,
>                           oldp, oldlenp, newp, newlen);
> -                     NET_UNLOCK();
>                       return (error);
>               }
>       return (ENOPROTOOPT);
> Index: net/if.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if.c,v
> retrieving revision 1.512
> diff -u -p -r1.512 if.c
> --- net/if.c  22 Aug 2017 15:02:34 -0000      1.512
> +++ net/if.c  13 Sep 2017 08:28:27 -0000
> @@ -2666,10 +2666,14 @@ ifpromisc(struct ifnet *ifp, int pswitch
>       return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
>  }
>  
> +/* XXX move to kern/uipc_mbuf.c */
>  int
>  sysctl_mq(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen, struct mbuf_queue *mq)
>  {
> +     unsigned int maxlen;
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -2678,8 +2682,14 @@ sysctl_mq(int *name, u_int namelen, void
>       case IFQCTL_LEN:
>               return (sysctl_rdint(oldp, oldlenp, newp, mq_len(mq)));
>       case IFQCTL_MAXLEN:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &mq->mq_maxlen)); /* XXX directly accessing maxlen */
> +             maxlen = mq->mq_maxlen;
> +             error = sysctl_int(oldp, oldlenp, newp, newlen, &maxlen);
> +             if (!error && maxlen != mq->mq_maxlen) {
> +                     mtx_enter(&mq->mq_mtx);
> +                     mq->mq_maxlen = maxlen;
> +                     mtx_leave(&mq->mq_mtx);
> +             }
> +             return (error);
>       case IFQCTL_DROPS:
>               return (sysctl_rdint(oldp, oldlenp, newp, mq_drops(mq)));
>       default:
> Index: net/if_etherip.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_etherip.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 if_etherip.c
> --- net/if_etherip.c  6 Jun 2017 11:51:13 -0000       1.19
> +++ net/if_etherip.c  13 Sep 2017 08:28:27 -0000
> @@ -662,18 +662,26 @@ int
>  ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return ENOTDIR;
>  
>       switch (name[0]) {
>       case ETHERIPCTL_ALLOW:
> -             return sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen, &etherip_allow);
> +             NET_UNLOCK();
> +             return (error);
>       case ETHERIPCTL_STATS:
>               if (newp != NULL)
>                       return EPERM;
> -             return sysctl_struct(oldp, oldlenp, newp, newlen,
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
>                   &etheripstat, sizeof(etheripstat));
> +             NET_UNLOCK();
> +             return (error);
>       default:
>               break;
>       }
> Index: net/pfkeyv2.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pfkeyv2.c,v
> retrieving revision 1.166
> diff -u -p -r1.166 pfkeyv2.c
> --- net/pfkeyv2.c     8 Sep 2017 05:36:53 -0000       1.166
> +++ net/pfkeyv2.c     13 Sep 2017 08:28:27 -0000
> @@ -2386,8 +2386,6 @@ pfkeyv2_sysctl(int *name, u_int namelen,
>       int error = EINVAL;
>       u_int rdomain;
>  
> -     NET_ASSERT_LOCKED();
> -
>       if (new)
>               return (EPERM);
>       if (namelen < 1)
> @@ -2403,7 +2401,9 @@ pfkeyv2_sysctl(int *name, u_int namelen,
>       case NET_KEY_SADB_DUMP:
>               if ((error = suser(curproc, 0)) != 0)
>                       return (error);
> +             NET_LOCK();
>               error = tdb_walk(rdomain, pfkeyv2_sysctl_walker, &w);
> +             NET_UNLOCK();
>               if (oldp)
>                       *oldlenp = w.w_where - oldp;
>               else
> @@ -2411,8 +2411,10 @@ pfkeyv2_sysctl(int *name, u_int namelen,
>               break;
>  
>       case NET_KEY_SPD_DUMP:
> +             NET_LOCK();
>               error = pfkeyv2_ipo_walk(rdomain,
>                   pfkeyv2_sysctl_policydumper, &w);
> +             NET_UNLOCK();
>               if (oldp)
>                       *oldlenp = w.w_where - oldp;
>               else
> Index: net/rtsock.c
> ===================================================================
> RCS file: /cvs/src/sys/net/rtsock.c,v
> retrieving revision 1.250
> diff -u -p -r1.250 rtsock.c
> --- net/rtsock.c      5 Sep 2017 07:59:11 -0000       1.250
> +++ net/rtsock.c      13 Sep 2017 08:28:27 -0000
> @@ -1733,8 +1733,6 @@ sysctl_rtable(int *name, u_int namelen, 
>       struct rt_tableinfo      tableinfo;
>       u_int                    tableid = 0;
>  
> -     NET_ASSERT_LOCKED();
> -
>       if (new)
>               return (EPERM);
>       if (namelen < 3 || namelen > 4)
> @@ -1757,6 +1755,7 @@ sysctl_rtable(int *name, u_int namelen, 
>       switch (w.w_op) {
>       case NET_RT_DUMP:
>       case NET_RT_FLAGS:
> +             NET_LOCK();
>               for (i = 1; i <= AF_MAX; i++) {
>                       if (af != 0 && af != i)
>                               continue;
> @@ -1767,10 +1766,13 @@ sysctl_rtable(int *name, u_int namelen, 
>                       if (error)
>                               break;
>               }
> +             NET_UNLOCK();
>               break;
>  
>       case NET_RT_IFLIST:
> +             NET_LOCK();
>               error = sysctl_iflist(af, &w);
> +             NET_UNLOCK();
>               break;
>  
>       case NET_RT_STATS:
> @@ -1786,7 +1788,9 @@ sysctl_rtable(int *name, u_int namelen, 
>                   &tableinfo, sizeof(tableinfo));
>               return (error);
>       case NET_RT_IFNAMES:
> +             NET_LOCK();
>               error = sysctl_ifnames(&w);
> +             NET_UNLOCK();
>               break;
>       }
>       free(w.w_tmem, M_RTABLE, 0);
> Index: netinet/igmp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/igmp.c,v
> retrieving revision 1.69
> diff -u -p -r1.69 igmp.c
> --- netinet/igmp.c    19 Jun 2017 17:58:49 -0000      1.69
> +++ netinet/igmp.c    13 Sep 2017 08:28:27 -0000
> @@ -680,6 +680,8 @@ int
>  igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -690,9 +692,13 @@ igmp_sysctl(int *name, u_int namelen, vo
>                       return (EPERM);
>               return (igmp_sysctl_igmpstat(oldp, oldlenp, newp));
>       default:
> -             if (name[0] < IGMPCTL_MAXID)
> -                     return (sysctl_int_arr(igmpctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < IGMPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(igmpctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>       /* NOTREACHED */
> Index: netinet/ip_carp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_carp.c,v
> retrieving revision 1.315
> diff -u -p -r1.315 ip_carp.c
> --- netinet/ip_carp.c 11 Aug 2017 21:24:19 -0000      1.315
> +++ netinet/ip_carp.c 13 Sep 2017 08:28:27 -0000
> @@ -739,6 +739,8 @@ int
>  carp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
> *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -749,8 +751,11 @@ carp_sysctl(int *name, u_int namelen, vo
>       default:
>               if (name[0] <= 0 || name[0] >= CARPCTL_MAXID)
>                       return (ENOPROTOOPT);
> -             return sysctl_int(oldp, oldlenp, newp, newlen,
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
>                   &carp_opts[name[0]]);
> +             NET_UNLOCK();
> +             return (error);
>       }
>  }
>  
> Index: netinet/ip_divert.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_divert.c,v
> retrieving revision 1.52
> diff -u -p -r1.52 ip_divert.c
> --- netinet/ip_divert.c       6 Sep 2017 11:43:04 -0000       1.52
> +++ netinet/ip_divert.c       13 Sep 2017 08:28:27 -0000
> @@ -367,23 +367,35 @@ int
>  divert_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
> *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
>       case DIVERTCTL_SENDSPACE:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &divert_sendspace));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &divert_sendspace);
> +             NET_UNLOCK();
> +             return (error);
>       case DIVERTCTL_RECVSPACE:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &divert_recvspace));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &divert_recvspace);
> +             NET_UNLOCK();
> +             return (error);
>       case DIVERTCTL_STATS:
>               return (divert_sysctl_divstat(oldp, oldlenp, newp));
>       default:
> -             if (name[0] < DIVERTCTL_MAXID)
> -                     return sysctl_int_arr(divertctl_vars, name, namelen,
> +             if (name[0] < DIVERTCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(divertctl_vars, name, namelen,
>                           oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>  
>               return (ENOPROTOOPT);
>       }
> Index: netinet/ip_ether.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_ether.c,v
> retrieving revision 1.86
> diff -u -p -r1.86 ip_ether.c
> --- netinet/ip_ether.c        19 Jun 2017 17:58:49 -0000      1.86
> +++ netinet/ip_ether.c        13 Sep 2017 08:29:36 -0000
> @@ -468,19 +468,27 @@ int
>  etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
>       case ETHERIPCTL_ALLOW:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &etherip_allow));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &etherip_allow);
> +             NET_UNLOCK();
> +             return (error);
>       case ETHERIPCTL_STATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &etheripstat, sizeof(etheripstat)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 &etheripstat, sizeof(etheripstat));
> +             NET_UNLOCK();
> +             return (error);
>       default:
>               return (ENOPROTOOPT);
>       }
> Index: netinet/ip_gre.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_gre.c,v
> retrieving revision 1.66
> diff -u -p -r1.66 ip_gre.c
> --- netinet/ip_gre.c  15 Aug 2017 17:47:15 -0000      1.66
> +++ netinet/ip_gre.c  13 Sep 2017 08:28:27 -0000
> @@ -373,15 +373,23 @@ int
>  gre_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>          /* All sysctl names at this level are terminal. */
>          if (namelen != 1)
>                  return (ENOTDIR);
>  
>          switch (name[0]) {
>          case GRECTL_ALLOW:
> -                return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_allow);
> +             NET_UNLOCK();
> +             return (error);
>          case GRECTL_WCCP:
> -                return (sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen, &gre_wccp);
> +             NET_UNLOCK();
> +             return (error);
>          default:
>                  return (ENOPROTOOPT);
>          }
> @@ -392,14 +400,19 @@ int
>  ipmobile_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>          /* All sysctl names at this level are terminal. */
>          if (namelen != 1)
>                  return (ENOTDIR);
>  
>          switch (name[0]) {
>          case MOBILEIPCTL_ALLOW:
> -                return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                                &ip_mobile_allow));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &ip_mobile_allow);
> +             NET_UNLOCK();
> +             return (error);
>          default:
>                  return (ENOPROTOOPT);
>          }
> Index: netinet/ip_icmp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
> retrieving revision 1.171
> diff -u -p -r1.171 ip_icmp.c
> --- netinet/ip_icmp.c 10 Aug 2017 02:26:26 -0000      1.171
> +++ netinet/ip_icmp.c 13 Sep 2017 08:28:27 -0000
> @@ -881,8 +881,6 @@ icmp_sysctl(int *name, u_int namelen, vo
>  {
>       int error;
>  
> -     NET_ASSERT_LOCKED();
> -
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -890,6 +888,7 @@ icmp_sysctl(int *name, u_int namelen, vo
>       switch (name[0]) {
>       case ICMPCTL_REDIRTIMEOUT:
>  
> +             NET_LOCK();
>               error = sysctl_int(oldp, oldlenp, newp, newlen,
>                   &icmp_redirtimeout);
>               if (icmp_redirect_timeout_q != NULL) {
> @@ -903,6 +902,7 @@ icmp_sysctl(int *name, u_int namelen, vo
>                       icmp_redirect_timeout_q =
>                           rt_timer_queue_create(icmp_redirtimeout);
>               }
> +             NET_UNLOCK();
>               break;
>  
>       case ICMPCTL_STATS:
> @@ -911,8 +911,10 @@ icmp_sysctl(int *name, u_int namelen, vo
>  
>       default:
>               if (name[0] < ICMPCTL_MAXID) {
> +                     NET_LOCK();
>                       error = sysctl_int_arr(icmpctl_vars, name, namelen,
>                           oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
>                       break;
>               }
>               error = ENOPROTOOPT;
> Index: netinet/ip_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_input.c,v
> retrieving revision 1.322
> diff -u -p -r1.322 ip_input.c
> --- netinet/ip_input.c        7 Sep 2017 10:54:49 -0000       1.322
> +++ netinet/ip_input.c        13 Sep 2017 08:28:27 -0000
> @@ -1617,26 +1617,24 @@ ip_sysctl(int *name, u_int namelen, void
>       extern struct mrtstat mrtstat;
>  #endif
>  
> -     NET_ASSERT_LOCKED();
> -
>       /* Almost all sysctl names at this level are terminal. */
>       if (namelen != 1 && name[0] != IPCTL_IFQUEUE)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
> -#ifdef notyet
> -     case IPCTL_DEFMTU:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
> -#endif
>       case IPCTL_SOURCEROUTE:
>               /*
>                * Don't allow this to change in a secure environment.
>                */
>               if (newp && securelevel > 0)
>                       return (EPERM);
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &ip_dosourceroute));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &ip_dosourceroute);
> +             NET_UNLOCK();
> +             return (error);
>       case IPCTL_MTUDISC:
> +             NET_LOCK();
>               error = sysctl_int(oldp, oldlenp, newp, newlen,
>                   &ip_mtudisc);
>               if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
> @@ -1646,25 +1644,37 @@ ip_sysctl(int *name, u_int namelen, void
>                       rt_timer_queue_destroy(ip_mtudisc_timeout_q);
>                       ip_mtudisc_timeout_q = NULL;
>               }
> +             NET_UNLOCK();
>               return error;
>       case IPCTL_MTUDISCTIMEOUT:
> +             NET_LOCK();
>               error = sysctl_int(oldp, oldlenp, newp, newlen,
>                  &ip_mtudisc_timeout);
>               if (ip_mtudisc_timeout_q != NULL)
>                       rt_timer_queue_change(ip_mtudisc_timeout_q,
>                                             ip_mtudisc_timeout);
> +             NET_UNLOCK();
>               return (error);
>       case IPCTL_IPSEC_ENC_ALGORITHM:
> -             return (sysctl_tstring(oldp, oldlenp, newp, newlen,
> -                                    ipsec_def_enc, sizeof(ipsec_def_enc)));
> +             NET_LOCK();
> +             error = sysctl_tstring(oldp, oldlenp, newp, newlen,
> +                                    ipsec_def_enc, sizeof(ipsec_def_enc));
> +             NET_UNLOCK();
> +             return (error);
>       case IPCTL_IPSEC_AUTH_ALGORITHM:
> -             return (sysctl_tstring(oldp, oldlenp, newp, newlen,
> +             NET_LOCK();
> +             error = sysctl_tstring(oldp, oldlenp, newp, newlen,
>                                      ipsec_def_auth,
> -                                    sizeof(ipsec_def_auth)));
> +                                    sizeof(ipsec_def_auth));
> +             NET_UNLOCK();
> +             return (error);
>       case IPCTL_IPSEC_IPCOMP_ALGORITHM:
> -             return (sysctl_tstring(oldp, oldlenp, newp, newlen,
> +             NET_LOCK();
> +             error = sysctl_tstring(oldp, oldlenp, newp, newlen,
>                                      ipsec_def_comp,
> -                                    sizeof(ipsec_def_comp)));
> +                                    sizeof(ipsec_def_comp));
> +             NET_UNLOCK();
> +             return (error);
>       case IPCTL_IFQUEUE:
>               return (sysctl_niq(name + 1, namelen - 1,
>                   oldp, oldlenp, newp, newlen, &ipintrq));
> @@ -1679,11 +1689,17 @@ ip_sysctl(int *name, u_int namelen, void
>       case IPCTL_MRTMFC:
>               if (newp)
>                       return (EPERM);
> -             return mrt_sysctl_mfc(oldp, oldlenp);
> +             NET_LOCK();
> +             error = mrt_sysctl_mfc(oldp, oldlenp);
> +             NET_UNLOCK();
> +             return (error);
>       case IPCTL_MRTVIF:
>               if (newp)
>                       return (EPERM);
> -             return mrt_sysctl_vif(oldp, oldlenp);
> +             NET_LOCK();
> +             error = mrt_sysctl_vif(oldp, oldlenp);
> +             NET_UNLOCK();
> +             return (error);
>  #else
>       case IPCTL_MRTPROTO:
>       case IPCTL_MRTSTATS:
> @@ -1692,9 +1708,13 @@ ip_sysctl(int *name, u_int namelen, void
>               return (EOPNOTSUPP);
>  #endif
>       default:
> -             if (name[0] < IPCTL_MAXID)
> -                     return (sysctl_int_arr(ipctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < IPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(ipctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (EOPNOTSUPP);
>       }
>       /* NOTREACHED */
> Index: netinet/ip_ipip.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_ipip.c,v
> retrieving revision 1.86
> diff -u -p -r1.86 ip_ipip.c
> --- netinet/ip_ipip.c 5 Jul 2017 11:34:10 -0000       1.86
> +++ netinet/ip_ipip.c 13 Sep 2017 08:28:27 -0000
> @@ -592,13 +592,18 @@ int
>  ipip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
> *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
>       case IPIPCTL_ALLOW:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen, &ipip_allow);
> +             NET_UNLOCK();
> +             return (error);
>       case IPIPCTL_STATS:
>               return (ipip_sysctl_ipipstat(oldp, oldlenp, newp));
>       default:
> Index: netinet/ipsec_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
> retrieving revision 1.156
> diff -u -p -r1.156 ipsec_input.c
> --- netinet/ipsec_input.c     5 Jul 2017 11:34:10 -0000       1.156
> +++ netinet/ipsec_input.c     13 Sep 2017 08:28:27 -0000
> @@ -615,6 +615,8 @@ int
>  esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -623,12 +625,19 @@ esp_sysctl(int *name, u_int namelen, voi
>       case ESPCTL_STATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &espstat, sizeof(espstat)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 &espstat, sizeof(espstat));
> +             NET_UNLOCK();
> +             return (error);
>       default:
> -             if (name[0] < ESPCTL_MAXID)
> -                     return (sysctl_int_arr(espctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < ESPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(espctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>  }
> @@ -637,6 +646,8 @@ int
>  ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -645,12 +656,19 @@ ah_sysctl(int *name, u_int namelen, void
>       case AHCTL_STATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &ahstat, sizeof(ahstat)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 &ahstat, sizeof(ahstat));
> +             NET_UNLOCK();
> +             return (error);
>       default:
> -             if (name[0] < AHCTL_MAXID)
> -                     return (sysctl_int_arr(ahctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < AHCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(ahctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>  }
> @@ -659,6 +677,8 @@ int
>  ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void 
> *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -667,12 +687,19 @@ ipcomp_sysctl(int *name, u_int namelen, 
>       case IPCOMPCTL_STATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &ipcompstat, sizeof(ipcompstat)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 &ipcompstat, sizeof(ipcompstat));
> +             NET_UNLOCK();
> +             return (error);
>       default:
> -             if (name[0] < IPCOMPCTL_MAXID)
> -                     return (sysctl_int_arr(ipcompctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < IPCOMPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(ipcompctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>  }
> Index: netinet/tcp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
> retrieving revision 1.155
> diff -u -p -r1.155 tcp_usrreq.c
> --- netinet/tcp_usrreq.c      5 Sep 2017 07:59:11 -0000       1.155
> +++ netinet/tcp_usrreq.c      13 Sep 2017 08:28:27 -0000
> @@ -955,8 +955,6 @@ tcp_sysctl(int *name, u_int namelen, voi
>  {
>       int error, nval;
>  
> -     NET_ASSERT_LOCKED();
> -
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
> @@ -964,73 +962,91 @@ tcp_sysctl(int *name, u_int namelen, voi
>       switch (name[0]) {
>  #ifdef TCP_SACK
>       case TCPCTL_SACK:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &tcp_do_sack));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &tcp_do_sack);
> +             NET_UNLOCK();
> +             return (error);
>  #endif
>       case TCPCTL_SLOWHZ:
>               return (sysctl_rdint(oldp, oldlenp, newp, PR_SLOWHZ));
>  
>       case TCPCTL_BADDYNAMIC:
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 baddynamicports.tcp, sizeof(baddynamicports.tcp)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 baddynamicports.tcp, sizeof(baddynamicports.tcp));
> +             NET_UNLOCK();
> +             return (error);
>  
>       case TCPCTL_ROOTONLY:
>               if (newp && securelevel > 0)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 rootonlyports.tcp, sizeof(rootonlyports.tcp)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 rootonlyports.tcp, sizeof(rootonlyports.tcp));
> +             NET_UNLOCK();
> +             return (error);
>  
>       case TCPCTL_IDENT:
> -             return (tcp_ident(oldp, oldlenp, newp, newlen, 0));
> +             NET_LOCK();
> +             error = tcp_ident(oldp, oldlenp, newp, newlen, 0);
> +             NET_UNLOCK();
> +             return (error);
>  
>       case TCPCTL_DROP:
> -             return (tcp_ident(oldp, oldlenp, newp, newlen, 1));
> +             NET_LOCK();
> +             error = tcp_ident(oldp, oldlenp, newp, newlen, 1);
> +             NET_UNLOCK();
> +             return (error);
>  
>       case TCPCTL_ALWAYS_KEEPALIVE:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &tcp_always_keepalive));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &tcp_always_keepalive);
> +             NET_UNLOCK();
> +             return (error);
>  
>  #ifdef TCP_ECN
>       case TCPCTL_ECN:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                &tcp_do_ecn));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                &tcp_do_ecn);
> +             NET_UNLOCK();
> +             return (error);
>  #endif
>       case TCPCTL_REASS_LIMIT:
> +             NET_LOCK();
>               nval = tcp_reass_limit;
>               error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
> -             if (error)
> -                     return (error);
> -             if (nval != tcp_reass_limit) {
> +             if (!error && nval != tcp_reass_limit) {
>                       error = pool_sethardlimit(&tcpqe_pool, nval, NULL, 0);
> -                     if (error)
> -                             return (error);
> -                     tcp_reass_limit = nval;
> +                     if (!error)
> +                             tcp_reass_limit = nval;
>               }
> -             return (0);
> +             NET_UNLOCK();
> +             return (error);
>  #ifdef TCP_SACK
>       case TCPCTL_SACKHOLE_LIMIT:
> +             NET_LOCK();
>               nval = tcp_sackhole_limit;
>               error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
> -             if (error)
> -                     return (error);
> -             if (nval != tcp_sackhole_limit) {
> +             if (!error && nval != tcp_sackhole_limit) {
>                       error = pool_sethardlimit(&sackhl_pool, nval, NULL, 0);
> -                     if (error)
> -                             return (error);
> -                     tcp_sackhole_limit = nval;
> +                     if (!error)
> +                             tcp_sackhole_limit = nval;
>               }
> -             return (0);
> +             NET_UNLOCK();
> +             return (error);
>  #endif
>  
>       case TCPCTL_STATS:
>               return (tcp_sysctl_tcpstat(oldp, oldlenp, newp));
>  
>       case TCPCTL_SYN_USE_LIMIT:
> +             NET_LOCK();
>               error = sysctl_int(oldp, oldlenp, newp, newlen,
>                   &tcp_syn_use_limit);
> -             if (error)
> -                     return (error);
> -             if (newp != NULL) {
> +             if (!error && newp != NULL) {
>                       /*
>                        * Global tcp_syn_use_limit is used when reseeding a
>                        * new cache.  Also update the value in active cache.
> @@ -1040,33 +1056,40 @@ tcp_sysctl(int *name, u_int namelen, voi
>                       if (tcp_syn_cache[1].scs_use > tcp_syn_use_limit)
>                               tcp_syn_cache[1].scs_use = tcp_syn_use_limit;
>               }
> -             return (0);
> +             NET_UNLOCK();
> +             return (error);
>  
>       case TCPCTL_SYN_HASH_SIZE:
> +             NET_LOCK();
>               nval = tcp_syn_hash_size;
>               error = sysctl_int(oldp, oldlenp, newp, newlen, &nval);
> -             if (error)
> -                     return (error);
> -             if (nval != tcp_syn_hash_size) {
> -                     if (nval < 1 || nval > 100000)
> -                             return (EINVAL);
> -                     /*
> -                      * If global hash size has been changed, switch sets as
> -                      * soon as possible.  Then the actual hash array will
> -                      * be reallocated.
> -                      */
> -                     if (tcp_syn_cache[0].scs_size != nval)
> -                             tcp_syn_cache[0].scs_use = 0;
> -                     if (tcp_syn_cache[1].scs_size != nval)
> -                             tcp_syn_cache[1].scs_use = 0;
> -                     tcp_syn_hash_size = nval;
> +             if (!error && nval != tcp_syn_hash_size) {
> +                     if (nval < 1 || nval > 100000) {
> +                             error = EINVAL;
> +                     } else {
> +                             /*
> +                              * If global hash size has been changed,
> +                              * switch sets as soon as possible.  Then
> +                              * the actual hash array will be reallocated.
> +                              */
> +                             if (tcp_syn_cache[0].scs_size != nval)
> +                                     tcp_syn_cache[0].scs_use = 0;
> +                             if (tcp_syn_cache[1].scs_size != nval)
> +                                     tcp_syn_cache[1].scs_use = 0;
> +                             tcp_syn_hash_size = nval;
> +                     }
>               }
> -             return (0);
> +             NET_UNLOCK();
> +             return (error);
>  
>       default:
> -             if (name[0] < TCPCTL_MAXID)
> -                     return (sysctl_int_arr(tcpctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < TCPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(tcpctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>       /* NOTREACHED */
> Index: netinet/udp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
> retrieving revision 1.240
> diff -u -p -r1.240 udp_usrreq.c
> --- netinet/udp_usrreq.c      5 Sep 2017 07:59:11 -0000       1.240
> +++ netinet/udp_usrreq.c      13 Sep 2017 08:28:27 -0000
> @@ -1277,20 +1277,28 @@ int
>  udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
>      size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
>       case UDPCTL_BADDYNAMIC:
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 baddynamicports.udp, sizeof(baddynamicports.udp)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 baddynamicports.udp, sizeof(baddynamicports.udp));
> +             NET_UNLOCK();
> +             return (error);
>  
>       case UDPCTL_ROOTONLY:
>               if (newp && securelevel > 0)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 rootonlyports.udp, sizeof(rootonlyports.udp)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 rootonlyports.udp, sizeof(rootonlyports.udp));
> +             NET_UNLOCK();
> +             return (error);
>  
>       case UDPCTL_STATS:
>               if (newp != NULL)
> @@ -1299,9 +1307,13 @@ udp_sysctl(int *name, u_int namelen, voi
>               return (udp_sysctl_udpstat(oldp, oldlenp, newp));
>  
>       default:
> -             if (name[0] < UDPCTL_MAXID)
> -                     return (sysctl_int_arr(udpctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < UDPCTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(udpctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (ENOPROTOOPT);
>       }
>       /* NOTREACHED */
> Index: netinet6/icmp6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/icmp6.c,v
> retrieving revision 1.216
> diff -u -p -r1.216 icmp6.c
> --- netinet6/icmp6.c  1 Sep 2017 15:05:31 -0000       1.216
> +++ netinet6/icmp6.c  13 Sep 2017 08:28:27 -0000
> @@ -1887,6 +1887,8 @@ int
>  icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return ENOTDIR;
> @@ -1896,9 +1898,13 @@ icmp6_sysctl(int *name, u_int namelen, v
>       case ICMPV6CTL_STATS:
>               return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp);
>       default:
> -             if (name[0] < ICMPV6CTL_MAXID)
> -                     return (sysctl_int_arr(icmpv6ctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < ICMPV6CTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(icmpv6ctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return ENOPROTOOPT;
>       }
>       /* NOTREACHED */
> Index: netinet6/ip6_divert.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
> retrieving revision 1.51
> diff -u -p -r1.51 ip6_divert.c
> --- netinet6/ip6_divert.c     6 Sep 2017 11:43:04 -0000       1.51
> +++ netinet6/ip6_divert.c     13 Sep 2017 08:28:27 -0000
> @@ -370,23 +370,35 @@ int
>  divert6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>      void *newp, size_t newlen)
>  {
> +     int error;
> +
>       /* All sysctl names at this level are terminal. */
>       if (namelen != 1)
>               return (ENOTDIR);
>  
>       switch (name[0]) {
>       case DIVERT6CTL_SENDSPACE:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &divert6_sendspace));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &divert6_sendspace);
> +             NET_UNLOCK();
> +             return (error);
>       case DIVERT6CTL_RECVSPACE:
> -             return (sysctl_int(oldp, oldlenp, newp, newlen,
> -                 &divert6_recvspace));
> +             NET_LOCK();
> +             error = sysctl_int(oldp, oldlenp, newp, newlen,
> +                 &divert6_recvspace);
> +             NET_UNLOCK();
> +             return (error);
>       case DIVERT6CTL_STATS:
>               return (divert6_sysctl_div6stat(oldp, oldlenp, newp));
>       default:
> -             if (name[0] < DIVERT6CTL_MAXID)
> -                     return sysctl_int_arr(divert6ctl_vars, name, namelen,
> +             if (name[0] < DIVERT6CTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(divert6ctl_vars, name, namelen,
>                           oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>  
>               return (ENOPROTOOPT);
>       }
> Index: netinet6/ip6_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
> retrieving revision 1.202
> diff -u -p -r1.202 ip6_input.c
> --- netinet6/ip6_input.c      22 Aug 2017 15:02:34 -0000      1.202
> +++ netinet6/ip6_input.c      13 Sep 2017 08:28:27 -0000
> @@ -1383,8 +1383,6 @@ ip6_sysctl(int *name, u_int namelen, voi
>  #endif
>       int error;
>  
> -     NET_ASSERT_LOCKED();
> -
>       /* Almost all sysctl names at this level are terminal. */
>       if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE)
>               return (ENOTDIR);
> @@ -1398,18 +1396,27 @@ ip6_sysctl(int *name, u_int namelen, voi
>       case IPV6CTL_MRTSTATS:
>               if (newp != NULL)
>                       return (EPERM);
> -             return (sysctl_struct(oldp, oldlenp, newp, newlen,
> -                 &mrt6stat, sizeof(mrt6stat)));
> +             NET_LOCK();
> +             error = sysctl_struct(oldp, oldlenp, newp, newlen,
> +                 &mrt6stat, sizeof(mrt6stat));
> +             NET_UNLOCK();
> +             return (error);
>       case IPV6CTL_MRTPROTO:
>               return sysctl_rdint(oldp, oldlenp, newp, ip6_mrtproto);
>       case IPV6CTL_MRTMIF:
>               if (newp)
>                       return (EPERM);
> -             return mrt6_sysctl_mif(oldp, oldlenp);
> +             NET_LOCK();
> +             error = mrt6_sysctl_mif(oldp, oldlenp);
> +             NET_UNLOCK();
> +             return (error);
>       case IPV6CTL_MRTMFC:
>               if (newp)
>                       return (EPERM);
> -             return mrt6_sysctl_mfc(oldp, oldlenp);
> +             NET_LOCK();
> +             error = mrt6_sysctl_mfc(oldp, oldlenp);
> +             NET_UNLOCK();
> +             return (error);
>  #else
>       case IPV6CTL_MRTSTATS:
>       case IPV6CTL_MRTPROTO:
> @@ -1418,19 +1425,25 @@ ip6_sysctl(int *name, u_int namelen, voi
>               return (EOPNOTSUPP);
>  #endif
>       case IPV6CTL_MTUDISCTIMEOUT:
> +             NET_LOCK();
>               error = sysctl_int(oldp, oldlenp, newp, newlen,
>                   &ip6_mtudisc_timeout);
>               if (icmp6_mtudisc_timeout_q != NULL)
>                       rt_timer_queue_change(icmp6_mtudisc_timeout_q,
>                           ip6_mtudisc_timeout);
> +             NET_UNLOCK();
>               return (error);
>       case IPV6CTL_IFQUEUE:
>               return (sysctl_niq(name + 1, namelen - 1,
>                   oldp, oldlenp, newp, newlen, &ip6intrq));
>       default:
> -             if (name[0] < IPV6CTL_MAXID)
> -                     return (sysctl_int_arr(ipv6ctl_vars, name, namelen,
> -                         oldp, oldlenp, newp, newlen));
> +             if (name[0] < IPV6CTL_MAXID) {
> +                     NET_LOCK();
> +                     error = sysctl_int_arr(ipv6ctl_vars, name, namelen,
> +                         oldp, oldlenp, newp, newlen);
> +                     NET_UNLOCK();
> +                     return (error);
> +             }
>               return (EOPNOTSUPP);
>       }
>       /* NOTREACHED */
>

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to