From: Alexander Bluhm Subject: Re: sysctl(2): push locking down to udp_sysctl() To: Vitaliy Makkoveev Cc: tech@openbsd.org Date: Wed, 4 Dec 2024 23:32:27 +0100 On Wed, Dec 04, 2024 at 11:36:24PM +0300, Vitaliy Makkoveev wrote: > Mostly to deliver protocol statistics lockless. Atomically accessed > `udpctl_vars' variables are already moved from net lock, sysctl(2) > related locks are useless for them. Complicated UDPCTL_BADDYNAMIC and > UDPCTL_ROOTONLY cases were left as is. OK bluhm@ > Index: sys/netinet/in_proto.c > =================================================================== > RCS file: /cvs/src/sys/netinet/in_proto.c,v > diff -u -p -r1.113 in_proto.c > --- sys/netinet/in_proto.c 22 Aug 2024 10:58:31 -0000 1.113 > +++ sys/netinet/in_proto.c 4 Dec 2024 20:19:32 -0000 > @@ -185,7 +185,8 @@ const struct protosw inetsw[] = { > .pr_type = SOCK_DGRAM, > .pr_domain = &inetdomain, > .pr_protocol = IPPROTO_UDP, > - .pr_flags = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET, > + .pr_flags = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET| > + PR_MPSYSCTL, > .pr_input = udp_input, > .pr_ctlinput = udp_ctlinput, > .pr_ctloutput = ip_ctloutput, > Index: sys/netinet/udp_usrreq.c > =================================================================== > RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v > diff -u -p -r1.327 udp_usrreq.c > --- sys/netinet/udp_usrreq.c 5 Nov 2024 22:44:20 -0000 1.327 > +++ sys/netinet/udp_usrreq.c 4 Dec 2024 20:19:32 -0000 > @@ -172,6 +172,7 @@ void udp_sbappend(struct inpcb *, struct > u_int32_t); > int udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); > void udp_notify(struct inpcb *, int); > +int udp_sysctl_locked(int *, u_int, void *, size_t *, void *, size_t); > int udp_sysctl_udpstat(void *, size_t *, void *); > > #ifndef UDB_INITIAL_HASH_SIZE > @@ -1259,19 +1260,50 @@ 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: > + case UDPCTL_ROOTONLY: { > + size_t savelen = *oldlenp; > + int error; > + > + if ((error = sysctl_vslock(oldp, savelen))) > + return (error); > + error = udp_sysctl_locked(name, namelen, oldp, oldlenp, > + newp, newlen); > + sysctl_vsunlock(oldp, savelen); > + > + return (error); > + } > + case UDPCTL_STATS: > + if (newp != NULL) > + return (EPERM); > + > + return (udp_sysctl_udpstat(oldp, oldlenp, newp)); > + > + default: > + return (sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars), > + name, namelen, oldp, oldlenp, newp, newlen)); > + } > + /* NOTREACHED */ > +} > + > +int > +udp_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp, > + void *newp, size_t newlen) > +{ > + int error = ENOPROTOOPT; > + > + switch (name[0]) { > + case UDPCTL_BADDYNAMIC: > NET_LOCK(); > error = sysctl_struct(oldp, oldlenp, newp, newlen, > baddynamicports.udp, sizeof(baddynamicports.udp)); > NET_UNLOCK(); > - return (error); > + break; > > case UDPCTL_ROOTONLY: > if (newp && securelevel > 0) > @@ -1280,20 +1312,10 @@ udp_sysctl(int *name, u_int namelen, voi > error = sysctl_struct(oldp, oldlenp, newp, newlen, > rootonlyports.udp, sizeof(rootonlyports.udp)); > NET_UNLOCK(); > - return (error); > - > - case UDPCTL_STATS: > - if (newp != NULL) > - return (EPERM); > - > - return (udp_sysctl_udpstat(oldp, oldlenp, newp)); > - > - default: > - error = sysctl_bounded_arr(udpctl_vars, nitems(udpctl_vars), > - name, namelen, oldp, oldlenp, newp, newlen); > - return (error); > + break; > } > - /* NOTREACHED */ > + > + return (error); > } > > int > Index: sys/netinet6/in6_proto.c > =================================================================== > RCS file: /cvs/src/sys/netinet6/in6_proto.c,v > diff -u -p -r1.119 in6_proto.c > --- sys/netinet6/in6_proto.c 20 Aug 2024 07:46:27 -0000 1.119 > +++ sys/netinet6/in6_proto.c 4 Dec 2024 20:19:32 -0000 > @@ -136,7 +136,8 @@ const struct protosw inet6sw[] = { > .pr_type = SOCK_DGRAM, > .pr_domain = &inet6domain, > .pr_protocol = IPPROTO_UDP, > - .pr_flags = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET, > + .pr_flags = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPINPUT|PR_MPSOCKET| > + PR_MPSYSCTL, > .pr_input = udp_input, > .pr_ctlinput = udp6_ctlinput, > .pr_ctloutput = ip6_ctloutput,