Mark `so_rcv' sockbuf of udp(4) sockets as SB_OWNLOCK.
authormvs <mvs@openbsd.org>
Sun, 31 Mar 2024 13:50:00 +0000 (13:50 +0000)
committermvs <mvs@openbsd.org>
Sun, 31 Mar 2024 13:50:00 +0000 (13:50 +0000)
sbappend*() and soreceive() of SB_MTXLOCK marked sockets uses `sb_mtx'
mutex(9) for protection, meanwhile buffer usage check and corresponding
sbwait() sleep still serialized by solock(). Mark udp(4) as SB_OWNLOCK
to avoid solock() serialization and rely to `sb_mtx' mutex(9). The
`sb_state' and `sb_flags' modifications must be protected by `sb_mtx'
too.

ok bluhm

sys/kern/sys_socket.c
sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/nfs/nfs_socket.c
sys/nfs/nfs_syscalls.c

index bba512b..e3b1a89 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_socket.c,v 1.62 2024/03/26 09:46:47 mvs Exp $     */
+/*     $OpenBSD: sys_socket.c,v 1.63 2024/03/31 13:50:00 mvs Exp $     */
 /*     $NetBSD: sys_socket.c,v 1.13 1995/08/12 23:59:09 mycroft Exp $  */
 
 /*
@@ -91,6 +91,7 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
 
        case FIOASYNC:
                solock(so);
+               mtx_enter(&so->so_rcv.sb_mtx);
                if (*(int *)data) {
                        so->so_rcv.sb_flags |= SB_ASYNC;
                        so->so_snd.sb_flags |= SB_ASYNC;
@@ -98,6 +99,7 @@ soo_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
                        so->so_rcv.sb_flags &= ~SB_ASYNC;
                        so->so_snd.sb_flags &= ~SB_ASYNC;
                }
+               mtx_leave(&so->so_rcv.sb_mtx);
                sounlock(so);
                break;
 
index 1d8a101..a904ac0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket.c,v 1.323 2024/03/27 22:47:53 mvs Exp $   */
+/*     $OpenBSD: uipc_socket.c,v 1.324 2024/03/31 13:50:00 mvs Exp $   */
 /*     $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $        */
 
 /*
@@ -155,6 +155,8 @@ soalloc(const struct protosw *prp, int wait)
        case AF_INET6:
                switch (prp->pr_type) {
                case SOCK_DGRAM:
+                       so->so_rcv.sb_flags |= SB_OWNLOCK;
+                       /* FALLTHROUGH */
                case SOCK_RAW:
                        so->so_rcv.sb_flags |= SB_MTXLOCK;
                        break;
@@ -1392,7 +1394,9 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
         * we sleep, the socket buffers are not marked as spliced yet.
         */
        if (somove(so, M_WAIT)) {
+               mtx_enter(&so->so_rcv.sb_mtx);
                so->so_rcv.sb_flags |= SB_SPLICE;
+               mtx_leave(&so->so_rcv.sb_mtx);
                sosp->so_snd.sb_flags |= SB_SPLICE;
        }
 
@@ -1420,7 +1424,9 @@ sounsplice(struct socket *so, struct socket *sosp, int freeing)
        task_del(sosplice_taskq, &so->so_splicetask);
        timeout_del(&so->so_idleto);
        sosp->so_snd.sb_flags &= ~SB_SPLICE;
+       mtx_enter(&so->so_rcv.sb_mtx);
        so->so_rcv.sb_flags &= ~SB_SPLICE;
+       mtx_leave(&so->so_rcv.sb_mtx);
        so->so_sp->ssp_socket = sosp->so_sp->ssp_soback = NULL;
        /* Do not wakeup a socket that is about to be freed. */
        if ((freeing & SOSP_FREEING_READ) == 0 && soreadable(so))
@@ -1678,6 +1684,7 @@ somove(struct socket *so, int wait)
                pru_rcvd(so);
 
        /* Receive buffer did shrink by len bytes, adjust oob. */
+       mtx_enter(&so->so_rcv.sb_mtx);
        rcvstate = so->so_rcv.sb_state;
        so->so_rcv.sb_state &= ~SS_RCVATMARK;
        oobmark = so->so_oobmark;
@@ -1688,6 +1695,7 @@ somove(struct socket *so, int wait)
                if (oobmark >= len)
                        oobmark = 0;
        }
+       mtx_leave(&so->so_rcv.sb_mtx);
 
        /*
         * Handle oob data.  If any malloc fails, ignore error.
index 4a9eaae..4fb4819 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket2.c,v 1.146 2024/03/27 22:47:53 mvs Exp $  */
+/*     $OpenBSD: uipc_socket2.c,v 1.147 2024/03/31 13:50:00 mvs Exp $  */
 /*     $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $       */
 
 /*
@@ -351,7 +351,9 @@ void
 socantrcvmore(struct socket *so)
 {
        soassertlocked(so);
+       mtx_enter(&so->so_rcv.sb_mtx);
        so->so_rcv.sb_state |= SS_CANTRCVMORE;
+       mtx_leave(&so->so_rcv.sb_mtx);
        sorwakeup(so);
 }
 
index 1743a0e..9760db8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_socket.c,v 1.146 2024/03/22 07:15:04 claudio Exp $        */
+/*     $OpenBSD: nfs_socket.c,v 1.147 2024/03/31 13:50:00 mvs Exp $    */
 /*     $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $  */
 
 /*
@@ -371,7 +371,9 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
        error = soreserve(so, sndreserve, rcvreserve);
        if (error)
                goto bad_locked;
+       mtx_enter(&so->so_rcv.sb_mtx);
        so->so_rcv.sb_flags |= SB_NOINTR;
+       mtx_leave(&so->so_rcv.sb_mtx);
        so->so_snd.sb_flags |= SB_NOINTR;
        sounlock(so);
 
index f3ccd3f..32f28f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_syscalls.c,v 1.122 2024/03/22 07:15:04 claudio Exp $      */
+/*     $OpenBSD: nfs_syscalls.c,v 1.123 2024/03/31 13:50:00 mvs Exp $  */
 /*     $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $   */
 
 /*
@@ -297,12 +297,12 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam)
                m_freem(m);
        }
        solock(so);
-       so->so_rcv.sb_flags &= ~SB_NOINTR;
        mtx_enter(&so->so_rcv.sb_mtx);
+       so->so_rcv.sb_flags &= ~SB_NOINTR;
        so->so_rcv.sb_timeo_nsecs = INFSLP;
        mtx_leave(&so->so_rcv.sb_mtx);
-       so->so_snd.sb_flags &= ~SB_NOINTR;
        mtx_enter(&so->so_snd.sb_mtx);
+       so->so_snd.sb_flags &= ~SB_NOINTR;
        so->so_snd.sb_timeo_nsecs = INFSLP;
        mtx_leave(&so->so_snd.sb_mtx);
        sounlock(so);