git: 459af94e43b0 - main - netinet6: Fix some issues with passing v4-mapped groups to IPv6 sockets.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Aug 2026 15:47:41 UTC
The branch main has been updated by bms:
URL: https://cgit.FreeBSD.org/src/commit/?id=459af94e43b0fe2ef91e14aa867c3b1aa1fb9690
commit 459af94e43b0fe2ef91e14aa867c3b1aa1fb9690
Author: Bruce M Simpson <bms@FreeBSD.org>
AuthorDate: 2026-08-02 13:09:57 +0000
Commit: Bruce M Simpson <bms@FreeBSD.org>
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