Introduce temporary PR_MPSYSCTL flag to mark (*pr_sysctl)() handler MP
authormvs <mvs@openbsd.org>
Tue, 16 May 2023 19:36:00 +0000 (19:36 +0000)
committermvs <mvs@openbsd.org>
Tue, 16 May 2023 19:36:00 +0000 (19:36 +0000)
safe. We have may of them, so use flag instead of pushing kernel lock
within.

Unlock ip_sysctl(). Still take kernel lock within IPCTL_MRTSTATS case.
It looks like `mrtstat' protection is inconsistent, so keep locking as
it was. Since `mrtstat' are counters, it make sense to rework them into
per CPU counters with separate diffs.

Feedback and ok from bluhm@

sys/kern/uipc_domain.c
sys/netinet/in_proto.c
sys/netinet/ip_input.c
sys/sys/protosw.h

index 3b5c0bb..aa38e09 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_domain.c,v 1.61 2023/05/04 09:40:36 mvs Exp $    */
+/*     $OpenBSD: uipc_domain.c,v 1.62 2023/05/16 19:36:00 mvs Exp $    */
 /*     $NetBSD: uipc_domain.c,v 1.14 1996/02/09 19:00:44 christos Exp $        */
 
 /*
@@ -244,10 +244,12 @@ net_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        protocol = name[1];
        for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
                if (pr->pr_protocol == protocol && pr->pr_sysctl) {
-                       KERNEL_LOCK();
+                       if ((pr->pr_flags & PR_MPSYSCTL) == 0)
+                               KERNEL_LOCK();
                        error = (*pr->pr_sysctl)(name + 2, namelen - 2,
                            oldp, oldlenp, newp, newlen);
-                       KERNEL_UNLOCK();
+                       if ((pr->pr_flags & PR_MPSYSCTL) == 0)
+                               KERNEL_UNLOCK();
                        return (error);
                }
        return (ENOPROTOOPT);
index c4087a7..2a49df5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_proto.c,v 1.99 2022/08/15 09:11:38 mvs Exp $       */
+/*     $OpenBSD: in_proto.c,v 1.100 2023/05/16 19:36:00 mvs Exp $      */
 /*     $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 christos Exp $   */
 
 /*
@@ -177,6 +177,7 @@ u_char ip_protox[IPPROTO_MAX];
 const struct protosw inetsw[] = {
 {
   .pr_domain   = &inetdomain,
+  .pr_flags    = PR_MPSYSCTL,
   .pr_init     = ip_init,
   .pr_slowtimo = ip_slowtimo,
   .pr_sysctl   = ip_sysctl
index 42c1c72..cfa703c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_input.c,v 1.383 2023/04/05 21:51:47 bluhm Exp $    */
+/*     $OpenBSD: ip_input.c,v 1.384 2023/05/16 19:36:00 mvs Exp $      */
 /*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */
 
 /*
@@ -1704,8 +1704,11 @@ ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
                return (ip_sysctl_ipstat(oldp, oldlenp, newp));
 #ifdef MROUTING
        case IPCTL_MRTSTATS:
-               return (sysctl_rdstruct(oldp, oldlenp, newp,
-                   &mrtstat, sizeof(mrtstat)));
+               KERNEL_LOCK();
+               error = sysctl_rdstruct(oldp, oldlenp, newp,
+                   &mrtstat, sizeof(mrtstat));
+               KERNEL_UNLOCK();
+               return (error);
        case IPCTL_MRTMFC:
                if (newp)
                        return (EPERM);
index 0109c07..d96fe61 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: protosw.h,v 1.59 2022/11/26 17:52:35 mvs Exp $        */
+/*     $OpenBSD: protosw.h,v 1.60 2023/05/16 19:36:00 mvs Exp $        */
 /*     $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */
 
 /*-
@@ -123,14 +123,16 @@ struct protosw {
  * PR_ADDR requires PR_ATOMIC;
  * PR_ADDR and PR_CONNREQUIRED are mutually exclusive.
  */
-#define        PR_ATOMIC       0x01            /* exchange atomic messages only */
-#define        PR_ADDR         0x02            /* addresses given with messages */
-#define        PR_CONNREQUIRED 0x04            /* connection required by protocol */
-#define        PR_WANTRCVD     0x08            /* want PRU_RCVD calls */
-#define        PR_RIGHTS       0x10            /* passes capabilities */
-#define        PR_ABRTACPTDIS  0x20            /* abort on accept(2) to disconnected
+#define        PR_ATOMIC       0x0001          /* exchange atomic messages only */
+#define        PR_ADDR         0x0002          /* addresses given with messages */
+#define        PR_CONNREQUIRED 0x0004          /* connection required by protocol */
+#define        PR_WANTRCVD     0x0008          /* want PRU_RCVD calls */
+#define        PR_RIGHTS       0x0010          /* passes capabilities */
+#define        PR_ABRTACPTDIS  0x0020          /* abort on accept(2) to disconnected
                                           socket */
-#define        PR_SPLICE       0x40            /* socket splicing is possible */
+#define        PR_SPLICE       0x0040          /* socket splicing is possible */
+#define        PR_MPSYSCTL     0x0080          /* (*pr_sysctl)() doesn't require
+                                          kernel lock */
 
 /*
  * The arguments to usrreq are: