Index | Thread | Search

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

Download raw body.

Thread
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,