Index: sys/kern/uipc_socket2.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/kern/uipc_socket2.c,v diff -u -p -u -p -r1.164 uipc_socket2.c --- sys/kern/uipc_socket2.c 5 Jan 2025 12:36:48 -0000 1.164 +++ sys/kern/uipc_socket2.c 16 Jan 2025 13:10:06 -0000 @@ -218,8 +218,7 @@ sonewconn(struct socket *head, int conns /* * Lock order will be `head' -> `so' while these sockets are linked. */ - if (persocket) - solock(so); + solock_nonet(so); /* * Inherit watermarks but those may get clamped in low mem situations. @@ -253,13 +252,12 @@ sonewconn(struct socket *head, int conns } if (persocket) - sounlock(so); + sounlock_nonet(so); return (so); fail: - if (persocket) - sounlock(so); + sounlock_nonet(so); sigio_free(&so->so_sigio); klist_free(&so->so_rcv.sb_klist); klist_free(&so->so_snd.sb_klist); @@ -363,12 +361,21 @@ solock_shared(struct socket *so) case PF_INET: case PF_INET6: NET_LOCK_SHARED(); - rw_enter_write(&so->so_lock); break; - default: - rw_enter_write(&so->so_lock); + } + rw_enter_write(&so->so_lock); +} + +void +solock_nonet(struct socket *so) +{ + switch (so->so_proto->pr_domain->dom_family) { + case PF_INET: + case PF_INET6: + NET_ASSERT_LOCKED(); break; } + rw_enter_write(&so->so_lock); } int @@ -416,16 +423,19 @@ sounlock(struct socket *so) void sounlock_shared(struct socket *so) { + rw_exit_write(&so->so_lock); switch (so->so_proto->pr_domain->dom_family) { case PF_INET: case PF_INET6: - rw_exit_write(&so->so_lock); NET_UNLOCK_SHARED(); break; - default: - rw_exit_write(&so->so_lock); - break; } +} + +void +sounlock_nonet(struct socket *so) +{ + rw_exit_write(&so->so_lock); } void Index: sys/kern/uipc_syscalls.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/kern/uipc_syscalls.c,v diff -u -p -u -p -r1.221 uipc_syscalls.c --- sys/kern/uipc_syscalls.c 5 Jan 2025 11:33:45 -0000 1.221 +++ sys/kern/uipc_syscalls.c 16 Jan 2025 13:10:06 -0000 @@ -247,34 +247,6 @@ sys_accept4(struct proc *p, void *v, reg SCARG(uap, anamelen), SCARG(uap, flags), retval)); } -void -doaccept_solock(struct socket *so, int take_netlock) -{ - if (take_netlock) { - switch (so->so_proto->pr_domain->dom_family) { - case PF_INET: - case PF_INET6: - NET_LOCK_SHARED(); - } - } - - rw_enter_write(&so->so_lock); -} - -void -doaccept_sounlock(struct socket *so, int release_netlock) -{ - rw_exit_write(&so->so_lock); - - if (release_netlock) { - switch (so->so_proto->pr_domain->dom_family) { - case PF_INET: - case PF_INET6: - NET_UNLOCK_SHARED(); - } - } -} - int doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen, int flags, register_t *retval) @@ -307,7 +279,7 @@ doaccept(struct proc *p, int sock, struc nam = m_get(M_WAIT, MT_SONAME); head = headfp->f_data; - doaccept_solock(head, 1); + solock_shared(head); if (isdnssocket(head) || (head->so_options & SO_ACCEPTCONN) == 0) { error = EINVAL; @@ -341,7 +313,7 @@ doaccept(struct proc *p, int sock, struc */ so = TAILQ_FIRST(&head->so_q); - doaccept_solock(so, 0); + solock_nonet(so); if (soqremque(so, 1) == 0) panic("accept"); @@ -353,7 +325,7 @@ doaccept(struct proc *p, int sock, struc /* connection has been removed from the listen queue */ knote(&head->so_rcv.sb_klist, 0); - doaccept_sounlock(head, 0); + sounlock_nonet(head); fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD | FWRITE | nflag; @@ -362,7 +334,7 @@ doaccept(struct proc *p, int sock, struc error = soaccept(so, nam); - doaccept_sounlock(so, 1); + sounlock_shared(so); if (error) goto out; @@ -385,7 +357,7 @@ doaccept(struct proc *p, int sock, struc return 0; out_unlock: - doaccept_sounlock(head, 1); + sounlock_shared(head); out: fdplock(fdp); fdremove(fdp, tmpfd); Index: sys/netinet/in_proto.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/in_proto.c,v diff -u -p -u -p -r1.121 in_proto.c --- sys/netinet/in_proto.c 5 Jan 2025 12:36:48 -0000 1.121 +++ sys/netinet/in_proto.c 16 Jan 2025 13:10:06 -0000 @@ -197,7 +197,8 @@ const struct protosw inetsw[] = { .pr_type = SOCK_STREAM, .pr_domain = &inetdomain, .pr_protocol = IPPROTO_TCP, - .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE| + PR_MPINPUT, .pr_input = tcp_input, .pr_ctlinput = tcp_ctlinput, .pr_ctloutput = tcp_ctloutput, Index: sys/netinet/tcp_input.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet/tcp_input.c,v diff -u -p -u -p -r1.422 tcp_input.c --- sys/netinet/tcp_input.c 10 Jan 2025 20:19:03 -0000 1.422 +++ sys/netinet/tcp_input.c 16 Jan 2025 13:10:06 -0000 @@ -605,6 +605,11 @@ findpcb: tcpstat_inc(tcps_noport); goto dropwithreset_ratelim; } + so = in_pcbsolock_ref(inp); + if (so == NULL) { + tcpstat_inc(tcps_noport); + goto dropwithreset_ratelim; + } KASSERT(sotoinpcb(inp->inp_socket) == inp); KASSERT(intotcpcb(inp) == NULL || intotcpcb(inp)->t_inpcb == inp); @@ -637,7 +642,6 @@ findpcb: else tiwin = th->th_win; - so = inp->inp_socket; if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { union syn_cache_sa src; union syn_cache_sa dst; @@ -726,6 +730,7 @@ findpcb: * in use for the reply, * do not free it. */ + so = NULL; m = *mp = NULL; goto drop; } else { @@ -733,13 +738,11 @@ findpcb: * We have created a * full-blown connection. */ - tp = NULL; in_pcbunref(inp); inp = in_pcbref(sotoinpcb(so)); tp = intotcpcb(inp); if (tp == NULL) goto badsyn; /*XXX*/ - } break; @@ -845,6 +848,7 @@ findpcb: tcpstat_inc(tcps_dropsyn); goto drop; } + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; } @@ -1020,6 +1024,7 @@ findpcb: if (so->so_snd.sb_cc || tp->t_flags & TF_NEEDOUTPUT) (void) tcp_output(tp); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; } @@ -1070,6 +1075,7 @@ findpcb: tp->t_flags &= ~TF_BLOCKOUTPUT; if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT)) (void) tcp_output(tp); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; } @@ -1262,6 +1268,8 @@ trimthenstep6: ((arc4random() & 0x7fffffff) | 0x8000); reuse = &iss; tp = tcp_close(tp); + in_pcbsounlock_rele(inp, so); + so = NULL; in_pcbunref(inp); inp = NULL; goto findpcb; @@ -2062,6 +2070,7 @@ dodata: /* XXX */ */ if (tp->t_flags & (TF_ACKNOW|TF_NEEDOUTPUT)) (void) tcp_output(tp); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; @@ -2091,6 +2100,7 @@ dropafterack: m_freem(m); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; @@ -2126,6 +2136,7 @@ dropwithreset: (tcp_seq)0, TH_RST|TH_ACK, m->m_pkthdr.ph_rtableid, now); } m_freem(m); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; @@ -2137,6 +2148,7 @@ drop: tcp_trace(TA_DROP, ostate, tp, otp, &saveti.caddr, 0, tlen); m_freem(m); + in_pcbsounlock_rele(inp, so); in_pcbunref(inp); return IPPROTO_DONE; } @@ -3531,15 +3543,18 @@ syn_cache_get(struct sockaddr *src, stru struct inpcb *inp, *oldinp; struct tcpcb *tp = NULL; struct mbuf *am; - struct socket *oso; + struct socket *oldso; u_int rtableid; NET_ASSERT_LOCKED(); + inp = sotoinpcb(so); + mtx_enter(&syn_cache_mtx); sc = syn_cache_lookup(src, dst, &scp, sotoinpcb(so)->inp_rtableid); if (sc == NULL) { mtx_leave(&syn_cache_mtx); + in_pcbsounlock_rele(inp, so); return (NULL); } @@ -3553,6 +3568,7 @@ syn_cache_get(struct sockaddr *src, stru refcnt_take(&sc->sc_refcnt); mtx_leave(&syn_cache_mtx); (void) syn_cache_respond(sc, m, now, do_ecn); + in_pcbsounlock_rele(inp, so); syn_cache_put(sc); return ((struct socket *)(-1)); } @@ -3567,12 +3583,13 @@ syn_cache_get(struct sockaddr *src, stru * connection when the SYN arrived. If we can't create * the connection, abort it. */ - oso = so; + oldso = so; + oldinp = inp; so = sonewconn(so, SS_ISCONNECTED, M_DONTWAIT); if (so == NULL) goto resetandabort; - - oldinp = sotoinpcb(oso); + soassertlocked(so); + soref(so); inp = sotoinpcb(so); #ifdef IPSEC @@ -3633,7 +3650,7 @@ syn_cache_get(struct sockaddr *src, stru (void) m_free(am); tp = intotcpcb(inp); - tp->t_flags = sototcpcb(oso)->t_flags & (TF_NOPUSH|TF_NODELAY); + tp->t_flags = sototcpcb(oldso)->t_flags & (TF_NOPUSH|TF_NODELAY); if (sc->sc_request_r_scale != 15) { tp->requested_s_scale = sc->sc_requested_s_scale; tp->request_r_scale = sc->sc_request_r_scale; @@ -3645,6 +3662,7 @@ syn_cache_get(struct sockaddr *src, stru tp->t_template = tcp_template(tp); if (tp->t_template == 0) { tp = tcp_drop(tp, ENOBUFS); /* destroys socket */ + in_pcbsounlock_rele(inp, so); so = NULL; goto abort; } @@ -3696,8 +3714,9 @@ syn_cache_get(struct sockaddr *src, stru tp->rcv_adv = tp->rcv_nxt + sc->sc_win; tp->last_ack_sent = tp->rcv_nxt; - tcpstat_inc(tcps_sc_completed); + in_pcbsounlock_rele(oldinp, oldso); syn_cache_put(sc); + tcpstat_inc(tcps_sc_completed); return (so); resetandabort: @@ -3707,6 +3726,8 @@ abort: m_freem(m); if (so != NULL) soabort(so); + in_pcbsounlock_rele(inp, so); + in_pcbsounlock_rele(oldinp, oldso); syn_cache_put(sc); tcpstat_inc(tcps_sc_aborted); return ((struct socket *)(-1)); @@ -3740,8 +3761,8 @@ syn_cache_reset(struct sockaddr *src, st } syn_cache_rm(sc); mtx_leave(&syn_cache_mtx); - tcpstat_inc(tcps_sc_reset); syn_cache_put(sc); + tcpstat_inc(tcps_sc_reset); } void @@ -3781,8 +3802,8 @@ syn_cache_unreach(const struct sockaddr syn_cache_rm(sc); mtx_leave(&syn_cache_mtx); - tcpstat_inc(tcps_sc_unreach); syn_cache_put(sc); + tcpstat_inc(tcps_sc_unreach); } /* @@ -3810,7 +3831,7 @@ syn_cache_add(struct sockaddr *src, stru struct syn_cache_head *scp; struct mbuf *ipopts; - NET_ASSERT_LOCKED(); + soassertlocked(so); tp = sototcpcb(so); @@ -3968,9 +3989,8 @@ syn_cache_add(struct sockaddr *src, stru if (syn_cache_respond(sc, m, now, do_ecn) == 0) { mtx_enter(&syn_cache_mtx); /* - * XXXSMP Currently exclusive netlock prevents another insert - * after our syn_cache_lookup() and before syn_cache_insert(). - * Double insert should be handled and not rely on netlock. + * Socket lock prevents another insert after our + * syn_cache_lookup() and before syn_cache_insert(). */ syn_cache_insert(sc, tp); mtx_leave(&syn_cache_mtx); Index: sys/netinet6/in6_proto.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet6/in6_proto.c,v diff -u -p -u -p -r1.124 in6_proto.c --- sys/netinet6/in6_proto.c 5 Jan 2025 12:36:48 -0000 1.124 +++ sys/netinet6/in6_proto.c 16 Jan 2025 13:10:06 -0000 @@ -147,7 +147,8 @@ const struct protosw inet6sw[] = { .pr_type = SOCK_STREAM, .pr_domain = &inet6domain, .pr_protocol = IPPROTO_TCP, - .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE, + .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ABRTACPTDIS|PR_SPLICE| + PR_MPINPUT, .pr_input = tcp_input, .pr_ctlinput = tcp6_ctlinput, .pr_ctloutput = tcp_ctloutput, Index: sys/netinet6/nd6.c =================================================================== RCS file: /mount/openbsd/cvs/src/sys/netinet6/nd6.c,v diff -u -p -u -p -r1.283 nd6.c --- sys/netinet6/nd6.c 4 Sep 2024 07:54:52 -0000 1.283 +++ sys/netinet6/nd6.c 16 Jan 2025 13:10:06 -0000 @@ -709,7 +709,9 @@ nd6_nud_hint(struct rtentry *rt) struct llinfo_nd6 *ln; struct ifnet *ifp; + /* XXX NET_ASSERT_LOCKED_EXCLUSIVE(); + */ ifp = if_get(rt->rt_ifidx); if (ifp == NULL) Index: sys/sys/socketvar.h =================================================================== RCS file: /mount/openbsd/cvs/src/sys/sys/socketvar.h,v diff -u -p -u -p -r1.138 socketvar.h --- sys/sys/socketvar.h 3 Jan 2025 12:56:15 -0000 1.138 +++ sys/sys/socketvar.h 16 Jan 2025 13:10:06 -0000 @@ -451,10 +451,12 @@ int sockargs(struct mbuf **, const void int sosleep_nsec(struct socket *, void *, int, const char *, uint64_t); void solock(struct socket *); void solock_shared(struct socket *); +void solock_nonet(struct socket *); int solock_persocket(struct socket *); void solock_pair(struct socket *, struct socket *); void sounlock(struct socket *); void sounlock_shared(struct socket *); +void sounlock_nonet(struct socket *); int sendit(struct proc *, int, struct msghdr *, int, register_t *); int recvit(struct proc *, int, struct msghdr *, caddr_t, register_t *);