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