git: 23d8e956fbe2 - main - icmp6: fix use-after-reference-release

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Tue, 27 May 2025 12:02:26 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=23d8e956fbe29418d74b78d98a453fcec1ad16da

commit 23d8e956fbe29418d74b78d98a453fcec1ad16da
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-05-22 08:25:55 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-05-27 09:47:43 +0000

    icmp6: fix use-after-reference-release
    
    We release the reference to the in6_ifaddr but retain a pointer to it.
    Copy the address itself, rather than keeping the pointer to fix this.
    
    The previous version was actually safe, because  ifa_free() uses an epoch
    callback to free it, so the pointer would have remained valid as long as we are
    in net_epoch.
    Change it to copying the address anyway because it is more obviously correct and
    will remain correct even if ifa_free() changes later.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D50460
---
 sys/netinet6/icmp6.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index eaf8514fd5cf..9ea640fd24c8 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -2391,7 +2391,7 @@ void
 icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
 {
 	struct ifnet *ifp;	/* my outgoing interface */
-	struct in6_addr *ifp_ll6;
+	struct in6_addr ifp_ll6;
 	struct in6_addr *router_ll6;
 	struct ip6_hdr *sip6;	/* m0 as struct ip6_hdr */
 	struct mbuf *m = NULL;	/* newly allocated one */
@@ -2461,8 +2461,7 @@ icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
 						 IN6_IFF_NOTREADY|
 						 IN6_IFF_ANYCAST)) == NULL)
 			goto fail;
-		ifp_ll6 = &ia->ia_addr.sin6_addr;
-		/* XXXRW: reference released prematurely. */
+		bcopy(&ia->ia_addr.sin6_addr, &ifp_ll6, sizeof(ifp_ll6));
 		ifa_free(&ia->ia_ifa);
 	}
 
@@ -2485,7 +2484,7 @@ icmp6_redirect_output(struct mbuf *m0, struct nhop_object *nh)
 	ip6->ip6_nxt = IPPROTO_ICMPV6;
 	ip6->ip6_hlim = 255;
 	/* ip6->ip6_src must be linklocal addr for my outgoing if. */
-	bcopy(ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
+	bcopy(&ifp_ll6, &ip6->ip6_src, sizeof(struct in6_addr));
 	bcopy(&sip6->ip6_src, &ip6->ip6_dst, sizeof(struct in6_addr));
 
 	/* ND Redirect */