Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Jan 2024 14:20:37 GMT
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 1165116ada35 - stable/13 - IPv6: fix problem with duplicate port assignment with v4-mapped addrs
Message-ID:  <202401101420.40AEKbmc041708@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=1165116ada353364e1d1570d1d23bb3d18d28394

commit 1165116ada353364e1d1570d1d23bb3d18d28394
Author:     Mike Karels <karels@FreeBSD.org>
AuthorDate: 2022-07-29 14:23:23 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-01-10 13:50:55 +0000

    IPv6: fix problem with duplicate port assignment with v4-mapped addrs
    
    In in_pcb_lport_dest(), if an IPv6 socket does not match any other IPv6
    socket using in6_pcblookup_local(), and if the socket can also connect
    to IPv4 (the INP_IPV4 vflag is set), check for IPv4 matches as well.
    Otherwise, we can allocate a port that is used by an IPv4 socket
    (possibly one created from IPv6 via the same procedure), and then
    connect() can fail with EADDRINUSE, when it could have succeeded if
    the bound port was not in use.
    
    PR:             265064
    Submitted by:   firk at cantconnect.ru (with modifications)
    Reviewed by:    bz, melifaro
    Differential Revision: https://reviews.freebsd.org/D36012
    
    (cherry picked from commit 637f317c6d9c0c689677f499fc78ac545b192071)
---
 sys/netinet/in_pcb.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 4c4f4050595a..61079db56bdb 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -758,7 +758,7 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
 	}
 
 #ifdef INET
-	laddr.s_addr = INADDR_ANY;
+	laddr.s_addr = INADDR_ANY;	/* used by INET6+INET below too */
 	if ((inp->inp_vflag & (INP_IPV4|INP_IPV6)) == INP_IPV4) {
 		if (lsa != NULL)
 			laddr = ((struct sockaddr_in *)lsa)->sin_addr;
@@ -809,9 +809,16 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
 #endif
 		} else {
 #ifdef INET6
-			if ((inp->inp_vflag & INP_IPV6) != 0)
+			if ((inp->inp_vflag & INP_IPV6) != 0) {
 				tmpinp = in6_pcblookup_local(pcbinfo,
 				    &inp->in6p_laddr, lport, lookupflags, cred);
+#ifdef INET
+				if (tmpinp == NULL &&
+				    (inp->inp_vflag & INP_IPV4))
+					tmpinp = in_pcblookup_local(pcbinfo,
+					    laddr, lport, lookupflags, cred);
+#endif
+			}
 #endif
 #if defined(INET) && defined(INET6)
 			else



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