git: 8bda9f9c56a9 - stable/14 - netlink: fix accessing freed memory

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Fri, 06 Oct 2023 14:25:03 UTC
The branch stable/14 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=8bda9f9c56a997d851e8fc2c20b5e37f072ecb4a

commit 8bda9f9c56a997d851e8fc2c20b5e37f072ecb4a
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2023-09-30 15:11:57 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2023-10-06 12:47:39 +0000

    netlink: fix accessing freed memory
    
    The check for if_addrlen in dump_iface() is not sufficient to determine
    if we still have a valid if_addr.  Rather than directly accessing if_addr
    check the STAILQ (for the first entry).
    This avoids panics when destroying cloned interfaces as experienced with
    net80211 wlan ones.
    
    Sponsored by:   The FreeBSD Foundation
    Reviewed by:    jhibbits (earlier version), kp
    Differential Revision: https://reviews.freebsd.org/D42027
    
    (cherry picked from commit 7d48224073ce14f0dd3db2d4e96876ac928b52f2)
---
 sys/netlink/route/iface.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index e1939c7681de..b6e120933f83 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -292,6 +292,7 @@ static bool
 dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr,
     int if_flags_mask)
 {
+	struct epoch_tracker et;
         struct ifinfomsg *ifinfo;
 
         NL_LOG(LOG_DEBUG3, "dumping interface %s data", if_name(ifp));
@@ -321,11 +322,15 @@ dump_iface(struct nl_writer *nw, if_t ifp, const struct nlmsghdr *hdr,
         nlattr_add_u8(nw, IFLA_PROTO_DOWN, val);
         nlattr_add_u8(nw, IFLA_LINKMODE, val);
 */
-        if (if_getaddrlen(ifp) != 0) {
-		struct ifaddr *ifa = if_getifaddr(ifp);
+	if (if_getaddrlen(ifp) != 0) {
+		struct ifaddr *ifa;
 
-                dump_sa(nw, IFLA_ADDRESS, ifa->ifa_addr);
-        }
+		NET_EPOCH_ENTER(et);
+		ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
+		if (ifa != NULL)
+			dump_sa(nw, IFLA_ADDRESS, ifa->ifa_addr);
+		NET_EPOCH_EXIT(et);
+	}
 
         if ((if_getbroadcastaddr(ifp) != NULL)) {
 		nlattr_add(nw, IFLA_BROADCAST, if_getaddrlen(ifp),