The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3d76be28ec6036273f8b5665e51f74b5c332e7eb

commit 3d76be28ec6036273f8b5665e51f74b5c332e7eb
Author:     Gleb Smirnoff <[email protected]>
AuthorDate: 2023-02-03 19:33:36 +0000
Commit:     Gleb Smirnoff <[email protected]>
CommitDate: 2023-02-03 19:33:36 +0000

    netinet6: require network epoch for in6_pcbconnect()
    
    This removes recursive epoch entry in the syncache case.  Fixes
    unprotected access to V_in6_ifaddrhead in in6_pcbladdr(), as
    well as access to prison IP address lists. It also matches what
    IPv4 in_pcbconnect() does.
    
    Reviewed by:            markj
    Differential revision:  https://reviews.freebsd.org/D38355
---
 sys/netinet/tcp_usrreq.c   |  3 +++
 sys/netinet6/in6_pcb.c     | 10 ++++------
 sys/netinet6/udp6_usrreq.c |  4 ++--
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 5d82e5138538..df71b1c88faa 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1471,13 +1471,16 @@ static int
 tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
 {
        struct inpcb *inp = tptoinpcb(tp);
+       struct epoch_tracker et;
        int error;
 
        INP_WLOCK_ASSERT(inp);
 
+       NET_EPOCH_ENTER(et);
        INP_HASH_WLOCK(&V_tcbinfo);
        error = in6_pcbconnect(inp, nam, td->td_ucred, true);
        INP_HASH_WUNLOCK(&V_tcbinfo);
+       NET_EPOCH_EXIT(et);
        if (error != 0)
                return (error);
 
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index aed0f26f89ba..a76997d75ff3 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -357,8 +357,8 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6,
        int error = 0;
        int scope_ambiguous = 0;
        struct in6_addr in6a;
-       struct epoch_tracker et;
 
+       NET_EPOCH_ASSERT();
        INP_WLOCK_ASSERT(inp);
        INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);        /* XXXRW: why? */
 
@@ -381,10 +381,8 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6,
        if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
                return (error);
 
-       NET_EPOCH_ENTER(et);
        error = in6_selectsrc_socket(sin6, inp->in6p_outputopts,
            inp, inp->inp_cred, scope_ambiguous, &in6a, NULL);
-       NET_EPOCH_EXIT(et);
        if (error)
                return (error);
 
@@ -422,6 +420,9 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, 
struct ucred *cred,
        struct sockaddr_in6 laddr6;
        int error;
 
+       NET_EPOCH_ASSERT();
+       INP_WLOCK_ASSERT(inp);
+       INP_HASH_WLOCK_ASSERT(pcbinfo);
        KASSERT(sin6->sin6_family == AF_INET6,
            ("%s: invalid address family for %p", __func__, sin6));
        KASSERT(sin6->sin6_len == sizeof(*sin6),
@@ -430,9 +431,6 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, 
struct ucred *cred,
        bzero(&laddr6, sizeof(laddr6));
        laddr6.sin6_family = AF_INET6;
 
-       INP_WLOCK_ASSERT(inp);
-       INP_HASH_WLOCK_ASSERT(pcbinfo);
-
 #ifdef ROUTE_MPATH
        if (CALC_FLOWID_OUTBOUND) {
                uint32_t hash_type, hash_val;
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 1ab838d60ac0..7ce4c9974228 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -1101,9 +1101,7 @@ udp6_close(struct socket *so)
 static int
 udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 {
-#ifdef INET
        struct epoch_tracker et;
-#endif
        struct inpcb *inp;
        struct inpcbinfo *pcbinfo;
        struct sockaddr_in6 *sin6;
@@ -1181,9 +1179,11 @@ udp6_connect(struct socket *so, struct sockaddr *nam, 
struct thread *td)
        vflagsav = inp->inp_vflag;
        inp->inp_vflag &= ~INP_IPV4;
        inp->inp_vflag |= INP_IPV6;
+       NET_EPOCH_ENTER(et);
        INP_HASH_WLOCK(pcbinfo);
        error = in6_pcbconnect(inp, nam, td->td_ucred, true);
        INP_HASH_WUNLOCK(pcbinfo);
+       NET_EPOCH_EXIT(et);
        /*
         * If connect succeeds, mark socket as connected. If
         * connect fails and socket is unbound, reset inp_vflag

Reply via email to