From: Vitaliy Makkoveev Subject: sysctl(2): push locking down to udp_sysctl() To: Alexander Bluhm , tech@openbsd.org Date: Wed, 4 Dec 2024 23:36:24 +0300 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. 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,