git: 459af94e43b0 - main - netinet6: Fix some issues with passing v4-mapped groups to IPv6 sockets.

Bruce M Simpson <[email protected]> Mon, 03 Aug 2026 15:47:41 +0000
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a70b81d.3ee83.35062d0d__35668.409108051$1785772230$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by bms:

URL: https://cgit.FreeBSD.org/src/commit/?id=459af94e43b0fe2ef91e14aa867c3b1aa1fb9690

commit 459af94e43b0fe2ef91e14aa867c3b1aa1fb9690
Author:     Bruce M Simpson <[email protected]>
AuthorDate: 2026-08-02 13:09:57 +0000
Commit:     Bruce M Simpson <[email protected]>
CommitDate: 2026-08-03 15:47:24 +0000

    netinet6: Fix some issues with passing v4-mapped groups to IPv6 sockets.
    
    1. EFAULT was happening because sooptcopyin() from inp_join_group() was
    seeing the user-space thread descriptor in the faked-up sockopt. So, do
    not attempt a user copyin(); defer to C99 initialization nulling sopt_td
    for us to force a KVA memcpy().
    
    2. It seems necessary to byte-swap ipv6mr_multiaddr.s6_addr32[3] on amd64
    for similar reasons as to how the user-space initialization needed for
    passing an IPv4-mapped group address also requires byte-swapping of the
    0x0000FFFF field for s6_addr32[2]; it is a direct assignment to a integer
    member of a struct, NOT a memcpy().
    
    3. The assignment to imr_interface within in6_v6_mreq_to_v4() was obfuscated
    by a cast back to its own type due to use of the IA_SIN() macro. Elided.
    
    With this change, the feature gap seems to be closed; tested with a simple
    link-scope IPv4 group under 224.0.0.0/24 with an mlx5(4) SR-IOV VF in bhyve.
    
    PR:             https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193246
    Differential Revision:  https://reviews.freebsd.org/D58590
---
 sys/netinet6/in6_mcast.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index bc7da2d14a04..036d58e5bd92 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -1924,7 +1924,7 @@ in6_v6_mreq_to_v4(struct ipv6_mreq *mreq, struct ip_mreq *mreq_v4)
 		error = EADDRNOTAVAIL;
 		goto out;
 	}
-	mreq_v4->imr_interface.s_addr = IA_SIN(ia)->sin_addr.s_addr;
+	mreq_v4->imr_interface.s_addr = ia->ia_addr.sin_addr.s_addr;
 	error = 0;
 
 out:
@@ -1991,12 +1991,11 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
 				.sopt_name    = IP_ADD_MEMBERSHIP,
 				.sopt_val     = &mreq_v4,
 				.sopt_valsize = sizeof(mreq_v4),
-				.sopt_rights  = sopt->sopt_rights,
-				.sopt_td      = sopt->sopt_td
+				.sopt_rights  = sopt->sopt_rights
 			};
 
 			mreq_v4.imr_multiaddr.s_addr =
-			    mreq.ipv6mr_multiaddr.s6_addr32[3];
+			    htonl(mreq.ipv6mr_multiaddr.s6_addr32[3]);
 			if (mreq.ipv6mr_interface == 0)
 				mreq_v4.imr_interface.s_addr = INADDR_ANY;
 			else
@@ -2333,12 +2332,11 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
 				.sopt_name    = IP_DROP_MEMBERSHIP,
 				.sopt_val     = &mreq_v4,
 				.sopt_valsize = sizeof(mreq_v4),
-				.sopt_rights  = sopt->sopt_rights,
-				.sopt_td      = sopt->sopt_td
+				.sopt_rights  = sopt->sopt_rights
 			};
 
 			mreq_v4.imr_multiaddr.s_addr =
-			    mreq.ipv6mr_multiaddr.s6_addr32[3];
+			    htonl(mreq.ipv6mr_multiaddr.s6_addr32[3]);
 			if (mreq.ipv6mr_interface == 0)
 				mreq_v4.imr_interface.s_addr = INADDR_ANY;
 			else