Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
sysctl(2): unlock ah_sysctl() and ipcomp_sysctl()
To:
Alexander Bluhm <bluhm@openbsd.org>, tech@openbsd.org
Date:
Fri, 6 Dec 2024 00:11:38 +0300

Download raw body.

Thread
  • Vitaliy Makkoveev:

    sysctl(2): unlock ah_sysctl() and ipcomp_sysctl()

Both are atomically accessed `ah_enable' and `ipcomp_enable' booleans
and per-CPU counters based statistics.

esp_sysctl() is much more system wide, so I want unlock it separately.

Index: sys/netinet/in_proto.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_proto.c,v
diff -u -p -r1.116 in_proto.c
--- sys/netinet/in_proto.c	4 Dec 2024 22:48:41 -0000	1.116
+++ sys/netinet/in_proto.c	5 Dec 2024 21:00:16 -0000
@@ -285,7 +285,7 @@ const struct protosw inetsw[] = {
   .pr_type	= SOCK_RAW,
   .pr_domain	= &inetdomain,
   .pr_protocol	= IPPROTO_AH,
-  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_input	= ah46_input,
   .pr_ctlinput	= ah4_ctlinput,
   .pr_ctloutput	= rip_ctloutput,
@@ -307,7 +307,7 @@ const struct protosw inetsw[] = {
   .pr_type	= SOCK_RAW,
   .pr_domain	= &inetdomain,
   .pr_protocol	= IPPROTO_IPCOMP,
-  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_input	= ipcomp46_input,
   .pr_ctloutput	= rip_ctloutput,
   .pr_usrreqs	= &rip_usrreqs,
Index: sys/netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
diff -u -p -r1.206 ipsec_input.c
--- sys/netinet/ipsec_input.c	16 Sep 2023 09:33:27 -0000	1.206
+++ sys/netinet/ipsec_input.c	5 Dec 2024 21:00:17 -0000
@@ -86,6 +86,11 @@
 
 #include "bpfilter.h"
 
+/*
+ * Locks used to protect data:
+ *	a	atomic
+ */
+
 void ipsec_common_ctlinput(u_int, int, struct sockaddr *, void *, int);
 
 #ifdef ENCDEBUG
@@ -114,8 +119,8 @@ int ipsec_exp_first_use = IPSEC_DEFAULT_
 int ipsec_expire_acquire = IPSEC_DEFAULT_EXPIRE_ACQUIRE;
 
 int esp_enable = 1;
-int ah_enable = 1;
-int ipcomp_enable = 0;
+int ah_enable = 1;		/* [a] */
+int ipcomp_enable = 0;		/* [a] */
 
 const struct sysctl_bounded_args espctl_vars[] = {
 	{ESPCTL_ENABLE, &esp_enable, 0, 1},
@@ -673,8 +678,6 @@ 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);
@@ -683,11 +686,8 @@ ah_sysctl(int *name, u_int namelen, void
 	case AHCTL_STATS:
 		return ah_sysctl_ahstat(oldp, oldlenp, newp);
 	default:
-		NET_LOCK();
-		error = sysctl_bounded_arr(ahctl_vars, nitems(ahctl_vars), name,
+		return sysctl_bounded_arr(ahctl_vars, nitems(ahctl_vars), name,
 		    namelen, oldp, oldlenp, newp, newlen);
-		NET_UNLOCK();
-		return (error);
 	}
 }
 
@@ -706,8 +706,6 @@ 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);
@@ -716,12 +714,9 @@ ipcomp_sysctl(int *name, u_int namelen, 
 	case IPCOMPCTL_STATS:
 		return ipcomp_sysctl_ipcompstat(oldp, oldlenp, newp);
 	default:
-		NET_LOCK();
-		error = sysctl_bounded_arr(ipcompctl_vars,
+		return sysctl_bounded_arr(ipcompctl_vars,
 		    nitems(ipcompctl_vars), name, namelen, oldp, oldlenp,
 		    newp, newlen);
-		NET_UNLOCK();
-		return (error);
 	}
 }
 
@@ -775,7 +770,7 @@ ah46_input(struct mbuf **mp, int *offp, 
 #if NPF > 0
 	    ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) ||
 #endif
-	    !ah_enable)
+	    !atomic_load_int(&ah_enable))
 		return ipsec_input_disabled(mp, offp, proto, af);
 
 	protoff = ipsec_protoff(*mp, *offp, af);
@@ -832,7 +827,7 @@ ipcomp46_input(struct mbuf **mp, int *of
 #if NPF > 0
 	    ((*mp)->m_pkthdr.pf.flags & PF_TAG_DIVERTED) ||
 #endif
-	    !ipcomp_enable)
+	    !atomic_load_int(&ipcomp_enable))
 		return ipsec_input_disabled(mp, offp, proto, af);
 
 	protoff = ipsec_protoff(*mp, *offp, af);
Index: sys/netinet/ipsec_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_output.c,v
diff -u -p -r1.98 ipsec_output.c
--- sys/netinet/ipsec_output.c	11 Feb 2024 01:27:45 -0000	1.98
+++ sys/netinet/ipsec_output.c	5 Dec 2024 21:00:17 -0000
@@ -92,8 +92,9 @@ ipsp_process_packet(struct mbuf *m, stru
 
 	/* Check that the transform is allowed by the administrator. */
 	if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) ||
-	    (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) ||
-	    (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) {
+	    (tdb->tdb_sproto == IPPROTO_AH && !atomic_load_int(&ah_enable)) ||
+	    (tdb->tdb_sproto == IPPROTO_IPCOMP &&
+	    !atomic_load_int(&ipcomp_enable))) {
 		DPRINTF("IPsec outbound packet dropped due to policy "
 		    "(check your sysctls)");
 		error = EHOSTUNREACH;
Index: sys/netinet6/in6_proto.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
diff -u -p -r1.120 in6_proto.c
--- sys/netinet6/in6_proto.c	4 Dec 2024 22:48:41 -0000	1.120
+++ sys/netinet6/in6_proto.c	5 Dec 2024 21:00:17 -0000
@@ -205,7 +205,7 @@ const struct protosw inet6sw[] = {
   .pr_type	= SOCK_RAW,
   .pr_domain	= &inet6domain,
   .pr_protocol	= IPPROTO_AH,
-  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_input	= ah46_input,
   .pr_ctloutput	= rip6_ctloutput,
   .pr_usrreqs	= &rip6_usrreqs,
@@ -225,7 +225,7 @@ const struct protosw inet6sw[] = {
   .pr_type	= SOCK_RAW,
   .pr_domain	= &inet6domain,
   .pr_protocol	= IPPROTO_IPCOMP,
-  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
+  .pr_flags	= PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
   .pr_input	= ipcomp46_input,
   .pr_ctloutput	= rip6_ctloutput,
   .pr_usrreqs	= &rip6_usrreqs,