From: Vitaliy Makkoveev Subject: Re: Please test: shared solock for all intet sockets within knote(9) routines To: Alexander Bluhm Cc: tech@openbsd.org Date: Thu, 1 Feb 2024 01:07:14 +0300 On Wed, Jan 31, 2024 at 10:25:47PM +0100, Alexander Bluhm wrote: > On Tue, Jan 30, 2024 at 05:39:43PM +0300, Vitaliy Makkoveev wrote: > > Please test it, but keep in mind, soassertlocked_readonly() could be > > required in some more places. > > I panics on i386 during regress. From the timestamps of the logs > I think it is one of these. Not that they run on two machines and > the remote one crashes. > > -rw-r--r-- 1 root wsrc 4863 Jan 31 13:06 sys/kern/sosplice/error/make.log > -rw-r--r-- 1 root wsrc 4510 Jan 31 13:07 sys/kern/sosplice/loop/make.log > -rw-r--r-- 1 root wsrc 8872 Jan 31 13:08 sys/kern/sosplice/perf/make.log > -rw-r--r-- 1 root wsrc 1490 Jan 31 14:08 sys/kern/sosplice/scapy/make.log > -rw-r--r-- 1 root wsrc 40256 Jan 31 14:09 sys/kern/sosplice/tcp/make.log > -rw-r--r-- 1 root wsrc 9162 Jan 31 14:10 sys/kern/sosplice/udp/make.log > > [-- MARK -- Wed Jan 31 13:05:00 2024] > panic: mutex 0xd7dfd9a0 not held in klist_rcv_soassertlk > Stopped at db_enter+0x4: popl %ebp > TID PID UID PRFLAGS PFLAGS CPU COMMAND > * 70542 31548 0 0x14000 0x200 1 softnet0 > db_enter() at db_enter+0x4 > panic(d0cbc0e4) at panic+0x7a > klist_rcv_soassertlk(d7dfd92c) at klist_rcv_soassertlk+0x3b > knote_locked(d7dfd9f0,0) at knote_locked+0x1a > sohasoutofband(d7dfd92c) at sohasoutofband+0x25 > tcp_input(f5802ea4,f5802ea0,6,2) at tcp_input+0x290d > ip_deliver(f5802ea4,f5802ea0,6,2) at ip_deliver+0xf4 > ipintr() at ipintr+0x52 > if_netisr(0) at if_netisr+0xd2 > taskq_thread(d82f5000) at taskq_thread+0x84 > https://www.openbsd.org/ddb.html describes the minimum info required in bug > reports. Insufficient info makes it difficult to find and fix bugs. > ddb{1}> [-- MARK -- Wed Jan 31 13:10:00 2024] Sorry, I forgot to change knote_locked() to knote() within sohasoutofband(). This diff fixes it. Also sblock() fix included. Since the `sb_klist' uses `sb_mtx' mutex(9) for protection, special `socket_klistops' is not required anymore and was removed. Index: sys/kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.315 diff -u -p -r1.315 uipc_socket.c --- sys/kern/uipc_socket.c 26 Jan 2024 18:24:23 -0000 1.315 +++ sys/kern/uipc_socket.c 31 Jan 2024 22:06:44 -0000 @@ -72,26 +72,20 @@ int filt_soread(struct knote *kn, long h void filt_sowdetach(struct knote *kn); int filt_sowrite(struct knote *kn, long hint); int filt_soexcept(struct knote *kn, long hint); -int filt_solisten(struct knote *kn, long hint); -int filt_somodify(struct kevent *kev, struct knote *kn); -int filt_soprocess(struct knote *kn, struct kevent *kev); -const struct filterops solisten_filtops = { - .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, - .f_attach = NULL, - .f_detach = filt_sordetach, - .f_event = filt_solisten, - .f_modify = filt_somodify, - .f_process = filt_soprocess, -}; +int filt_snd_somodify(struct kevent *kev, struct knote *kn); +int filt_snd_soprocess(struct knote *kn, struct kevent *kev); + +int filt_rcv_somodify(struct kevent *kev, struct knote *kn); +int filt_rcv_soprocess(struct knote *kn, struct kevent *kev); const struct filterops soread_filtops = { .f_flags = FILTEROP_ISFD | FILTEROP_MPSAFE, .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soread, - .f_modify = filt_somodify, - .f_process = filt_soprocess, + .f_modify = filt_rcv_somodify, + .f_process = filt_rcv_soprocess, }; const struct filterops sowrite_filtops = { @@ -99,8 +93,8 @@ const struct filterops sowrite_filtops = .f_attach = NULL, .f_detach = filt_sowdetach, .f_event = filt_sowrite, - .f_modify = filt_somodify, - .f_process = filt_soprocess, + .f_modify = filt_snd_somodify, + .f_process = filt_snd_soprocess, }; const struct filterops soexcept_filtops = { @@ -108,18 +102,8 @@ const struct filterops soexcept_filtops .f_attach = NULL, .f_detach = filt_sordetach, .f_event = filt_soexcept, - .f_modify = filt_somodify, - .f_process = filt_soprocess, -}; - -void klist_soassertlk(void *); -int klist_solock(void *); -void klist_sounlock(void *, int); - -const struct klistops socket_klistops = { - .klo_assertlk = klist_soassertlk, - .klo_lock = klist_solock, - .klo_unlock = klist_sounlock, + .f_modify = filt_rcv_somodify, + .f_process = filt_rcv_soprocess, }; #ifndef SOMINCONN @@ -158,8 +142,10 @@ soalloc(const struct domain *dp, int wai return (NULL); rw_init_flags(&so->so_lock, dp->dom_name, RWL_DUPOK); refcnt_init(&so->so_refcnt); - klist_init(&so->so_rcv.sb_klist, &socket_klistops, so); - klist_init(&so->so_snd.sb_klist, &socket_klistops, so); + mtx_init(&so->so_rcv.sb_mtx, IPL_MPFLOOR); + mtx_init(&so->so_snd.sb_mtx, IPL_MPFLOOR); + klist_init_mutex(&so->so_rcv.sb_klist, &so->so_rcv.sb_mtx); + klist_init_mutex(&so->so_snd.sb_klist, &so->so_snd.sb_mtx); sigio_init(&so->so_sigio); TAILQ_INIT(&so->so_q0); TAILQ_INIT(&so->so_q); @@ -1757,7 +1743,7 @@ somove(struct socket *so, int wait) void sorwakeup(struct socket *so) { - soassertlocked(so); + soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (so->so_rcv.sb_flags & SB_SPLICE) { @@ -1785,7 +1771,7 @@ sorwakeup(struct socket *so) void sowwakeup(struct socket *so) { - soassertlocked(so); + soassertlocked_readonly(so); #ifdef SOCKET_SPLICE if (so->so_snd.sb_flags & SB_SPLICE) @@ -2134,7 +2120,46 @@ void sohasoutofband(struct socket *so) { pgsigio(&so->so_sigio, SIGURG, 0); - knote_locked(&so->so_rcv.sb_klist, 0); + knote(&so->so_rcv.sb_klist, 0); +} + +void +sofilt_lock(struct socket *so, struct sockbuf *sb) +{ + switch (so->so_proto->pr_domain->dom_family) { + case PF_INET: + case PF_INET6: + NET_LOCK_SHARED(); + break; + default: + rw_enter_write(&so->so_lock); + break; + } + + mtx_enter(&sb->sb_mtx); +} + +void +sofilt_unlock(struct socket *so, struct sockbuf *sb) +{ + mtx_leave(&sb->sb_mtx); + + switch (so->so_proto->pr_domain->dom_family) { + case PF_INET: + case PF_INET6: + NET_UNLOCK_SHARED(); + break; + default: + rw_exit_write(&so->so_lock); + break; + } +} + +static inline void +sofilt_assert_locked(struct socket *so, struct sockbuf *sb) +{ + MUTEX_ASSERT_LOCKED(&sb->sb_mtx); + soassertlocked_readonly(so); } int @@ -2143,13 +2168,9 @@ soo_kqfilter(struct file *fp, struct kno struct socket *so = kn->kn_fp->f_data; struct sockbuf *sb; - solock(so); switch (kn->kn_filter) { case EVFILT_READ: - if (so->so_options & SO_ACCEPTCONN) - kn->kn_fop = &solisten_filtops; - else - kn->kn_fop = &soread_filtops; + kn->kn_fop = &soread_filtops; sb = &so->so_rcv; break; case EVFILT_WRITE: @@ -2161,12 +2182,12 @@ soo_kqfilter(struct file *fp, struct kno sb = &so->so_rcv; break; default: - sounlock(so); return (EINVAL); } + mtx_enter(&sb->sb_mtx); klist_insert_locked(&sb->sb_klist, kn); - sounlock(so); + mtx_leave(&sb->sb_mtx); return (0); } @@ -2185,7 +2206,23 @@ filt_soread(struct knote *kn, long hint) struct socket *so = kn->kn_fp->f_data; int rv = 0; - soassertlocked(so); + sofilt_assert_locked(so, &so->so_rcv); + + if (so->so_options & SO_ACCEPTCONN) { + kn->kn_data = so->so_qlen; + rv = (kn->kn_data != 0); + + if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { + if (so->so_state & SS_ISDISCONNECTED) { + kn->kn_flags |= __EV_HUP; + rv = 1; + } else { + rv = soreadable(so); + } + } + + return rv; + } kn->kn_data = so->so_rcv.sb_cc; #ifdef SOCKET_SPLICE @@ -2226,7 +2263,7 @@ filt_sowrite(struct knote *kn, long hint struct socket *so = kn->kn_fp->f_data; int rv; - soassertlocked(so); + sofilt_assert_locked(so, &so->so_snd); kn->kn_data = sbspace(so, &so->so_snd); if (so->so_snd.sb_state & SS_CANTSENDMORE) { @@ -2257,7 +2294,7 @@ filt_soexcept(struct knote *kn, long hin struct socket *so = kn->kn_fp->f_data; int rv = 0; - soassertlocked(so); + sofilt_assert_locked(so, &so->so_rcv); #ifdef SOCKET_SPLICE if (isspliced(so)) { @@ -2283,77 +2320,55 @@ filt_soexcept(struct knote *kn, long hin } int -filt_solisten(struct knote *kn, long hint) +filt_snd_somodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; - int active; - - soassertlocked(so); - - kn->kn_data = so->so_qlen; - active = (kn->kn_data != 0); + int rv; - if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) { - if (so->so_state & SS_ISDISCONNECTED) { - kn->kn_flags |= __EV_HUP; - active = 1; - } else { - active = soreadable(so); - } - } + sofilt_lock(so, &so->so_snd); + rv = knote_modify(kev, kn); + sofilt_unlock(so, &so->so_snd); - return (active); + return (rv); } int -filt_somodify(struct kevent *kev, struct knote *kn) +filt_snd_soprocess(struct knote *kn, struct kevent *kev) { struct socket *so = kn->kn_fp->f_data; int rv; - solock(so); - rv = knote_modify(kev, kn); - sounlock(so); + sofilt_lock(so, &so->so_snd); + rv = knote_process(kn, kev); + sofilt_unlock(so, &so->so_snd); return (rv); } int -filt_soprocess(struct knote *kn, struct kevent *kev) +filt_rcv_somodify(struct kevent *kev, struct knote *kn) { struct socket *so = kn->kn_fp->f_data; int rv; - solock(so); - rv = knote_process(kn, kev); - sounlock(so); + sofilt_lock(so, &so->so_rcv); + rv = knote_modify(kev, kn); + sofilt_unlock(so, &so->so_rcv); return (rv); } -void -klist_soassertlk(void *arg) -{ - struct socket *so = arg; - - soassertlocked(so); -} - int -klist_solock(void *arg) +filt_rcv_soprocess(struct knote *kn, struct kevent *kev) { - struct socket *so = arg; - - solock(so); - return (1); -} + struct socket *so = kn->kn_fp->f_data; + int rv; -void -klist_sounlock(void *arg, int ls) -{ - struct socket *so = arg; + sofilt_lock(so, &so->so_rcv); + rv = knote_process(kn, kev); + sofilt_unlock(so, &so->so_rcv); - sounlock(so); + return (rv); } #ifdef DDB Index: sys/kern/uipc_socket2.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket2.c,v retrieving revision 1.140 diff -u -p -r1.140 uipc_socket2.c --- sys/kern/uipc_socket2.c 11 Jan 2024 14:15:11 -0000 1.140 +++ sys/kern/uipc_socket2.c 31 Jan 2024 22:06:44 -0000 @@ -439,7 +439,7 @@ sounlock_shared(struct socket *so) } void -soassertlocked(struct socket *so) +soassertlocked_readonly(struct socket *so) { switch (so->so_proto->pr_domain->dom_family) { case PF_INET: @@ -452,6 +452,27 @@ soassertlocked(struct socket *so) } } +void +soassertlocked(struct socket *so) +{ + switch (so->so_proto->pr_domain->dom_family) { + case PF_INET: + case PF_INET6: + if (rw_status(&netlock) == RW_READ) { + NET_ASSERT_LOCKED(); + + if (splassert_ctl > 0 && pru_locked(so) == 0 && + rw_status(&so->so_lock) != RW_WRITE) + splassert_fail(0, RW_WRITE, __func__); + } else + NET_ASSERT_LOCKED_EXCLUSIVE(); + break; + default: + rw_assert_wrlock(&so->so_lock); + break; + } +} + int sosleep_nsec(struct socket *so, void *ident, int prio, const char *wmesg, uint64_t nsecs) @@ -489,46 +510,62 @@ sbwait(struct socket *so, struct sockbuf soassertlocked(so); + mtx_enter(&sb->sb_mtx); sb->sb_flags |= SB_WAIT; + mtx_leave(&sb->sb_mtx); + return sosleep_nsec(so, &sb->sb_cc, prio, "netio", sb->sb_timeo_nsecs); } int sblock(struct socket *so, struct sockbuf *sb, int flags) { - int error, prio = PSOCK; + int error = 0, prio = PSOCK; soassertlocked(so); + mtx_enter(&sb->sb_mtx); if ((sb->sb_flags & SB_LOCK) == 0) { sb->sb_flags |= SB_LOCK; - return (0); + goto out; + } + if ((flags & SBL_WAIT) == 0) { + error = EWOULDBLOCK; + goto out; } - if ((flags & SBL_WAIT) == 0) - return (EWOULDBLOCK); if (!(flags & SBL_NOINTR || sb->sb_flags & SB_NOINTR)) prio |= PCATCH; while (sb->sb_flags & SB_LOCK) { sb->sb_flags |= SB_WANT; + mtx_leave(&sb->sb_mtx); error = sosleep_nsec(so, &sb->sb_flags, prio, "netlck", INFSLP); if (error) return (error); + mtx_enter(&sb->sb_mtx); } sb->sb_flags |= SB_LOCK; - return (0); +out: + mtx_leave(&sb->sb_mtx); + + return (error); } void sbunlock(struct socket *so, struct sockbuf *sb) { - soassertlocked(so); + int dowakeup = 0; + mtx_enter(&sb->sb_mtx); sb->sb_flags &= ~SB_LOCK; if (sb->sb_flags & SB_WANT) { sb->sb_flags &= ~SB_WANT; - wakeup(&sb->sb_flags); + dowakeup = 1; } + mtx_leave(&sb->sb_mtx); + + if (dowakeup) + wakeup(&sb->sb_flags); } /* @@ -539,15 +576,24 @@ sbunlock(struct socket *so, struct sockb void sowakeup(struct socket *so, struct sockbuf *sb) { - soassertlocked(so); + int dowakeup = 0, dopgsigio = 0; + mtx_enter(&sb->sb_mtx); if (sb->sb_flags & SB_WAIT) { sb->sb_flags &= ~SB_WAIT; - wakeup(&sb->sb_cc); + dowakeup = 1; } if (sb->sb_flags & SB_ASYNC) - pgsigio(&so->so_sigio, SIGIO, 0); + dopgsigio = 1; + knote_locked(&sb->sb_klist, 0); + mtx_leave(&sb->sb_mtx); + + if (dowakeup) + wakeup(&sb->sb_cc); + + if (dopgsigio) + pgsigio(&so->so_sigio, SIGIO, 0); } /* Index: sys/kern/uipc_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.216 diff -u -p -r1.216 uipc_syscalls.c --- sys/kern/uipc_syscalls.c 3 Jan 2024 11:07:04 -0000 1.216 +++ sys/kern/uipc_syscalls.c 31 Jan 2024 22:06:44 -0000 @@ -326,7 +326,7 @@ doaccept(struct proc *p, int sock, struc : (flags & SOCK_NONBLOCK ? FNONBLOCK : 0); /* connection has been removed from the listen queue */ - knote_locked(&head->so_rcv.sb_klist, 0); + knote(&head->so_rcv.sb_klist, 0); if (persocket) sounlock(head); Index: sys/netinet/ip_divert.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_divert.c,v retrieving revision 1.92 diff -u -p -r1.92 ip_divert.c --- sys/netinet/ip_divert.c 16 Sep 2023 09:33:27 -0000 1.92 +++ sys/netinet/ip_divert.c 31 Jan 2024 22:06:44 -0000 @@ -67,6 +67,7 @@ const struct pr_usrreqs divert_usrreqs = .pru_detach = divert_detach, .pru_lock = divert_lock, .pru_unlock = divert_unlock, + .pru_locked = divert_locked, .pru_bind = divert_bind, .pru_shutdown = divert_shutdown, .pru_send = divert_send, @@ -311,6 +312,14 @@ divert_unlock(struct socket *so) NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); +} + +int +divert_locked(struct socket *so) +{ + struct inpcb *inp = sotoinpcb(so); + + return mtx_owned(&inp->inp_mtx); } int Index: sys/netinet/ip_divert.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_divert.h,v retrieving revision 1.24 diff -u -p -r1.24 ip_divert.h --- sys/netinet/ip_divert.h 17 Oct 2022 14:49:02 -0000 1.24 +++ sys/netinet/ip_divert.h 31 Jan 2024 22:06:44 -0000 @@ -74,6 +74,7 @@ int divert_attach(struct socket *, int, int divert_detach(struct socket *); void divert_lock(struct socket *); void divert_unlock(struct socket *); +int divert_locked(struct socket *); int divert_bind(struct socket *, struct mbuf *, struct proc *); int divert_shutdown(struct socket *); int divert_send(struct socket *, struct mbuf *, struct mbuf *, Index: sys/netinet/ip_var.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_var.h,v retrieving revision 1.110 diff -u -p -r1.110 ip_var.h --- sys/netinet/ip_var.h 26 Nov 2023 22:08:10 -0000 1.110 +++ sys/netinet/ip_var.h 31 Jan 2024 22:06:44 -0000 @@ -260,6 +260,7 @@ int rip_attach(struct socket *, int, in int rip_detach(struct socket *); void rip_lock(struct socket *); void rip_unlock(struct socket *); +int rip_locked(struct socket *); int rip_bind(struct socket *, struct mbuf *, struct proc *); int rip_connect(struct socket *, struct mbuf *); int rip_disconnect(struct socket *); Index: sys/netinet/raw_ip.c =================================================================== RCS file: /cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.154 diff -u -p -r1.154 raw_ip.c --- sys/netinet/raw_ip.c 21 Jan 2024 01:17:20 -0000 1.154 +++ sys/netinet/raw_ip.c 31 Jan 2024 22:06:44 -0000 @@ -108,6 +108,7 @@ const struct pr_usrreqs rip_usrreqs = { .pru_detach = rip_detach, .pru_lock = rip_lock, .pru_unlock = rip_unlock, + .pru_locked = rip_locked, .pru_bind = rip_bind, .pru_connect = rip_connect, .pru_disconnect = rip_disconnect, @@ -522,6 +523,14 @@ rip_unlock(struct socket *so) NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); +} + +int +rip_locked(struct socket *so) +{ + struct inpcb *inp = sotoinpcb(so); + + return mtx_owned(&inp->inp_mtx); } int Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.316 diff -u -p -r1.316 udp_usrreq.c --- sys/netinet/udp_usrreq.c 28 Jan 2024 20:34:25 -0000 1.316 +++ sys/netinet/udp_usrreq.c 31 Jan 2024 22:06:44 -0000 @@ -127,6 +127,7 @@ const struct pr_usrreqs udp_usrreqs = { .pru_detach = udp_detach, .pru_lock = udp_lock, .pru_unlock = udp_unlock, + .pru_locked = udp_locked, .pru_bind = udp_bind, .pru_connect = udp_connect, .pru_disconnect = udp_disconnect, @@ -143,6 +144,7 @@ const struct pr_usrreqs udp6_usrreqs = { .pru_detach = udp_detach, .pru_lock = udp_lock, .pru_unlock = udp_unlock, + .pru_locked = udp_locked, .pru_bind = udp_bind, .pru_connect = udp_connect, .pru_disconnect = udp_disconnect, @@ -1154,6 +1156,14 @@ udp_unlock(struct socket *so) NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); +} + +int +udp_locked(struct socket *so) +{ + struct inpcb *inp = sotoinpcb(so); + + return mtx_owned(&inp->inp_mtx); } int Index: sys/netinet/udp_var.h =================================================================== RCS file: /cvs/src/sys/netinet/udp_var.h,v retrieving revision 1.50 diff -u -p -r1.50 udp_var.h --- sys/netinet/udp_var.h 10 Jan 2024 16:44:30 -0000 1.50 +++ sys/netinet/udp_var.h 31 Jan 2024 22:06:44 -0000 @@ -147,6 +147,7 @@ int udp_attach(struct socket *, int, in int udp_detach(struct socket *); void udp_lock(struct socket *); void udp_unlock(struct socket *); +int udp_locked(struct socket *); int udp_bind(struct socket *, struct mbuf *, struct proc *); int udp_connect(struct socket *, struct mbuf *); int udp_disconnect(struct socket *); Index: sys/netinet6/ip6_mroute.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v retrieving revision 1.138 diff -u -p -r1.138 ip6_mroute.c --- sys/netinet6/ip6_mroute.c 6 Dec 2023 09:27:17 -0000 1.138 +++ sys/netinet6/ip6_mroute.c 31 Jan 2024 22:06:44 -0000 @@ -861,12 +861,12 @@ socket6_send(struct socket *so, struct m mtx_enter(&inp->inp_mtx); ret = sbappendaddr(so, &so->so_rcv, sin6tosa(src), mm, NULL); + if (ret != 0) + sorwakeup(so); mtx_leave(&inp->inp_mtx); - if (ret != 0) { - sorwakeup(so); + if (ret != 0) return 0; - } } m_freem(mm); return -1; Index: sys/netinet6/ip6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_var.h,v retrieving revision 1.109 diff -u -p -r1.109 ip6_var.h --- sys/netinet6/ip6_var.h 3 Dec 2023 20:36:24 -0000 1.109 +++ sys/netinet6/ip6_var.h 31 Jan 2024 22:06:44 -0000 @@ -353,6 +353,7 @@ int rip6_attach(struct socket *, int, in int rip6_detach(struct socket *); void rip6_lock(struct socket *); void rip6_unlock(struct socket *); +int rip6_locked(struct socket *); int rip6_bind(struct socket *, struct mbuf *, struct proc *); int rip6_connect(struct socket *, struct mbuf *); int rip6_disconnect(struct socket *); Index: sys/netinet6/raw_ip6.c =================================================================== RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.179 diff -u -p -r1.179 raw_ip6.c --- sys/netinet6/raw_ip6.c 21 Jan 2024 01:17:20 -0000 1.179 +++ sys/netinet6/raw_ip6.c 31 Jan 2024 22:06:44 -0000 @@ -110,6 +110,7 @@ const struct pr_usrreqs rip6_usrreqs = { .pru_detach = rip6_detach, .pru_lock = rip6_lock, .pru_unlock = rip6_unlock, + .pru_locked = rip6_locked, .pru_bind = rip6_bind, .pru_connect = rip6_connect, .pru_disconnect = rip6_disconnect, @@ -651,6 +652,14 @@ rip6_unlock(struct socket *so) NET_ASSERT_LOCKED(); mtx_leave(&inp->inp_mtx); +} + +int +rip6_locked(struct socket *so) +{ + struct inpcb *inp = sotoinpcb(so); + + return mtx_owned(&inp->inp_mtx); } int Index: sys/sys/mutex.h =================================================================== RCS file: /cvs/src/sys/sys/mutex.h,v retrieving revision 1.19 diff -u -p -r1.19 mutex.h --- sys/sys/mutex.h 1 Dec 2023 14:37:22 -0000 1.19 +++ sys/sys/mutex.h 31 Jan 2024 22:06:44 -0000 @@ -127,6 +127,9 @@ void mtx_leave(struct mutex *); #define mtx_init(m, ipl) mtx_init_flags(m, ipl, NULL, 0) +#define mtx_owned(mtx) \ + (((mtx)->mtx_owner == curcpu()) || panicstr || db_active) + #ifdef WITNESS void _mtx_init_flags(struct mutex *, int, const char *, int, Index: sys/sys/protosw.h =================================================================== RCS file: /cvs/src/sys/sys/protosw.h,v retrieving revision 1.64 diff -u -p -r1.64 protosw.h --- sys/sys/protosw.h 11 Jan 2024 14:15:12 -0000 1.64 +++ sys/sys/protosw.h 31 Jan 2024 22:06:44 -0000 @@ -69,6 +69,7 @@ struct pr_usrreqs { int (*pru_detach)(struct socket *); void (*pru_lock)(struct socket *); void (*pru_unlock)(struct socket *); + int (*pru_locked)(struct socket *so); int (*pru_bind)(struct socket *, struct mbuf *, struct proc *); int (*pru_listen)(struct socket *); int (*pru_connect)(struct socket *, struct mbuf *); @@ -294,6 +295,14 @@ pru_unlock(struct socket *so) { if (so->so_proto->pr_usrreqs->pru_unlock) (*so->so_proto->pr_usrreqs->pru_unlock)(so); +} + +static inline int +pru_locked(struct socket *so) +{ + if (so->so_proto->pr_usrreqs->pru_locked) + return (*so->so_proto->pr_usrreqs->pru_locked)(so); + return (0); } static inline int Index: sys/sys/socketvar.h =================================================================== RCS file: /cvs/src/sys/sys/socketvar.h,v retrieving revision 1.121 diff -u -p -r1.121 socketvar.h --- sys/sys/socketvar.h 11 Jan 2024 14:15:12 -0000 1.121 +++ sys/sys/socketvar.h 31 Jan 2024 22:06:44 -0000 @@ -40,6 +40,7 @@ #include /* for struct sigio_ref */ #include #include +#include #include #include @@ -105,6 +106,7 @@ struct socket { * Variables for socket buffering. */ struct sockbuf { + struct mutex sb_mtx; /* The following fields are all zeroed on flush. */ #define sb_startzero sb_cc u_long sb_cc; /* actual chars in buffer */ @@ -174,6 +176,7 @@ struct socket { #include void soassertlocked(struct socket *); +void soassertlocked_readonly(struct socket *); static inline void soref(struct socket *so) @@ -200,9 +203,16 @@ sorele(struct socket *so) static inline int sb_notify(struct socket *so, struct sockbuf *sb) { + int rv; + soassertlocked(so); - return ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || + + mtx_enter(&sb->sb_mtx); + rv = ((sb->sb_flags & (SB_WAIT|SB_ASYNC|SB_SPLICE)) != 0 || !klist_empty(&sb->sb_klist)); + mtx_leave(&sb->sb_mtx); + + return rv; } /* @@ -211,10 +221,12 @@ sb_notify(struct socket *so, struct sock * still be negative (cc > hiwat or mbcnt > mbmax). Should detect * overflow and return 0. */ + static inline long sbspace(struct socket *so, struct sockbuf *sb) { - soassertlocked(so); + soassertlocked_readonly(so); + return lmin(sb->sb_hiwat - sb->sb_cc, sb->sb_mbmax - sb->sb_mbcnt); } @@ -230,7 +242,7 @@ sbspace(struct socket *so, struct sockbu static inline int soreadable(struct socket *so) { - soassertlocked(so); + soassertlocked_readonly(so); if (isspliced(so)) return 0; return (so->so_rcv.sb_state & SS_CANTRCVMORE) || so->so_qlen || @@ -241,7 +253,7 @@ soreadable(struct socket *so) static inline int sowriteable(struct socket *so) { - soassertlocked(so); + soassertlocked_readonly(so); return ((sbspace(so, &so->so_snd) >= so->so_snd.sb_lowat && ((so->so_state & SS_ISCONNECTED) || (so->so_proto->pr_flags & PR_CONNREQUIRED)==0)) ||