Introduce a mutex per inpcb to serialize access to socket receive
authorbluhm <bluhm@openbsd.org>
Sun, 21 Aug 2022 11:44:53 +0000 (11:44 +0000)
committerbluhm <bluhm@openbsd.org>
Sun, 21 Aug 2022 11:44:53 +0000 (11:44 +0000)
buffer.  Later it may be used to protect more of the PCB or socket.
In divert input replace the kernel lock with this mutex.
OK mvs@

sys/netinet/in_pcb.c
sys/netinet/in_pcb.h
sys/netinet/ip_divert.c
sys/netinet6/ip6_divert.c

index e5700bb..903a03b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.c,v 1.270 2022/08/08 12:06:30 bluhm Exp $      */
+/*     $OpenBSD: in_pcb.c,v 1.271 2022/08/21 11:44:53 bluhm Exp $      */
 /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
 
 /*
@@ -236,6 +236,7 @@ in_pcballoc(struct socket *so, struct inpcbtable *table)
        inp->inp_table = table;
        inp->inp_socket = so;
        refcnt_init_trace(&inp->inp_refcnt, DT_REFCNT_IDX_INPCB);
+       mtx_init(&inp->inp_mtx, IPL_SOFTNET);
        inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT;
        inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
        inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;
index c14aa4b..9d19225 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: in_pcb.h,v 1.129 2022/05/15 09:12:20 dlg Exp $        */
+/*     $OpenBSD: in_pcb.h,v 1.130 2022/08/21 11:44:53 bluhm Exp $      */
 /*     $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $     */
 
 /*
@@ -79,6 +79,7 @@
  *     I       immutable after creation
  *     N       net lock
  *     t       inpt_mtx                pcb table mutex
+ *     p       inpcb_mtx               pcb mutex
  */
 
 struct pf_state_key;
@@ -121,6 +122,7 @@ struct inpcb {
 #define        inp_route       inp_ru.ru_route
 #define        inp_route6      inp_ru.ru_route6
        struct    refcnt inp_refcnt;    /* refcount PCB, delay memory free */
+       struct    mutex inp_mtx;        /* protect PCB and socket members */
        int       inp_flags;            /* generic IP/datagram flags */
        union {                         /* Header prototype. */
                struct ip hu_ip;
index b843fc9..adf8b09 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip_divert.c,v 1.70 2022/08/20 23:48:58 mvs Exp $ */
+/*      $OpenBSD: ip_divert.c,v 1.71 2022/08/21 11:44:54 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -228,22 +228,15 @@ divert_packet(struct mbuf *m, int dir, u_int16_t divert_port)
                if_put(ifp);
        }
 
+       mtx_enter(&inp->inp_mtx);
        so = inp->inp_socket;
-       /*
-        * XXXSMP sbappendaddr() is not MP safe and this function is called
-        * from pf with shared netlock.  To call only one sbappendaddr() from
-        * divert_packet(), protect it with kernel lock.  All other places
-        * call sbappendaddr() with exclusive net lock.  This blocks
-        * divert_packet() as we have the shared lock.
-        */
-       KERNEL_LOCK();
        if (sbappendaddr(so, &so->so_rcv, sintosa(&sin), m, NULL) == 0) {
-               KERNEL_UNLOCK();
+               mtx_leave(&inp->inp_mtx);
                divstat_inc(divs_fullsock);
                goto bad;
        }
-       sorwakeup(inp->inp_socket);
-       KERNEL_UNLOCK();
+       mtx_leave(&inp->inp_mtx);
+       sorwakeup(so);
 
        in_pcbunref(inp);
        return;
index bf7d443..679278e 100644 (file)
@@ -1,4 +1,4 @@
-/*      $OpenBSD: ip6_divert.c,v 1.69 2022/08/20 23:48:58 mvs Exp $ */
+/*      $OpenBSD: ip6_divert.c,v 1.70 2022/08/21 11:44:54 bluhm Exp $ */
 
 /*
  * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -234,22 +234,15 @@ divert6_packet(struct mbuf *m, int dir, u_int16_t divert_port)
                if_put(ifp);
        }
 
+       mtx_enter(&inp->inp_mtx);
        so = inp->inp_socket;
-       /*
-        * XXXSMP sbappendaddr() is not MP safe and this function is called
-        * from pf with shared netlock.  To call only one sbappendaddr() from
-        * divert_packet(), protect it with kernel lock.  All other places
-        * call sbappendaddr() with exclusive net lock.  This blocks
-        * divert_packet() as we have the shared lock.
-        */
-       KERNEL_LOCK();
        if (sbappendaddr(so, &so->so_rcv, sin6tosa(&sin6), m, NULL) == 0) {
-               KERNEL_UNLOCK();
+               mtx_leave(&inp->inp_mtx);
                div6stat_inc(div6s_fullsock);
                goto bad;
        }
-       sorwakeup(inp->inp_socket);
-       KERNEL_UNLOCK();
+       mtx_leave(&inp->inp_mtx);
+       sorwakeup(so);
 
        in_pcbunref(inp);
        return;