Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 3 Feb 2023 19:34:20 GMT
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 3d76be28ec60 - main - netinet6: require network epoch for in6_pcbconnect()
Message-ID:  <202302031934.313JYKn3041412@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by glebius:

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

commit 3d76be28ec6036273f8b5665e51f74b5c332e7eb
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2023-02-03 19:33:36 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202302031934.313JYKn3041412>