From a53159c8db2afb9e19751e414617413817b31820 Mon Sep 17 00:00:00 2001 From: "Jack.zhang" Date: Wed, 19 Jul 2023 17:46:46 +0800 Subject: [PATCH] zebra:fix a zebra crash issue caused by mac change When the MAC address of the neighbor changes, a possible crash issue may occur. In the zebra_evpn_local_neigh_update function, the value of old_zmac (n->mac) will be updated to the new MAC address when the neighbor's MAC address changes. The pointer to the memory that this pointer points to may be released in the zebra_evpn_local_neigh_deref_mac function. This will cause old_zmac to become a dangling pointer. Accessing this dangling pointer in the zebra_evpn_ip_inherit_dad_from_mac function below will cause the zebra process to crash. Here is the backtrace: (gdb) bt 0 0x00007fc12c5f1fbf in raise () from /lib/x86_64-linux-gnu/libpthread.so.0 1 0x00007fc12d52e19c in core_handler (signo=11, siginfo=0x7ffda1fd1570, context=) at lib/sigevent.c:262 2 3 zebra_evpn_ip_inherit_dad_from_mac (zvrf=, old_zmac=0x5579ac3ca520, new_zmac=0x5579aba82f80, nbr=0x5579abd65ec0) at zebra/ze 4 0x00005579aa8dbf6d in zebra_evpn_local_neigh_update (zevpn=0x5579abb81440, ifp=ifp@entry=0x5579ab8a1640, ip=ip@entry=0x7ffda1fd1b40, macadd local_inactive=local_inactive@entry=253, dp_static=false) at zebra/zebra_evpn_neigh.c:1729 5 0x00005579aa9190a9 in zebra_vxlan_handle_kernel_neigh_update (ifp=ifp@entry=0x5579ab8a1640, link_if=link_if@entry=0x5579abd14f90, ip=ip@ent is_ext=is_ext@entry=false, is_router=, local_inactive=false, dp_static=false) at zebra/zebra_vxlan.c:3791 6 0x00005579aa8b3048 in netlink_ipneigh_change (h=0x7ffda1fd1d50, len=, ns_id=) at zebra/rt_netlink.c:3649 7 0x00005579aa8ac667 in netlink_parse_info (filter=filter@entry=0x5579aa8ab630 , nl=nl@entry=0x5579ab5861e8, zns=z startup=startup@entry=0) at zebra/kernel_netlink.c:965 8 0x00005579aa8ac8c8 in kernel_read (thread=) at zebra/kernel_netlink.c:402 9 0x00007fc12d53e60b in thread_call (thread=thread@entry=0x7ffda1fd9fd0) at lib/thread.c:1834 10 0x00007fc12d4fba78 in frr_run (master=0x5579ab3a1740) at lib/libfrr.c:1155 11 0x00005579aa89c6e3 in main (argc=11, argv=0x7ffda1fda3c8) at zebra/main.c:485 (gdb) f 3 3 zebra_evpn_ip_inherit_dad_from_mac (zvrf=, old_zmac=0x5579ac3ca520, new_zmac=0x5579aba82f80, nbr=0x5579abd65ec0) at zebra/ze 1230 zebra/zebra_evpn_neigh.c: No such file or directory. (gdb) p *old_zmac Cannot access memory at address 0x5579ac3ca520 (gdb) To fix this issue, the ZEBRA_MAC_DUPLICATE flag should be retrieved before old_zmac is released and used in the zebra_evpn_ip_inherit_dad_from_mac function. Signed-off-by: Jack.zhang --- zebra/zebra_evpn_neigh.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c index 74141e4f34..a00d8c969a 100644 --- a/zebra/zebra_evpn_neigh.c +++ b/zebra/zebra_evpn_neigh.c @@ -1038,11 +1038,10 @@ static inline void zebra_evpn_local_neigh_update_log( * from MAC. */ static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, - struct zebra_mac *old_zmac, + bool is_old_mac_dup, struct zebra_mac *new_zmac, struct zebra_neigh *nbr) { - bool is_old_mac_dup = false; bool is_new_mac_dup = false; if (!zebra_evpn_do_dup_addr_detect(zvrf)) @@ -1050,9 +1049,6 @@ static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, /* Check old or new MAC is detected as duplicate * mark this neigh as duplicate */ - if (old_zmac) - is_old_mac_dup = - CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE); if (new_zmac) is_new_mac_dup = CHECK_FLAG(new_zmac->flags, ZEBRA_MAC_DUPLICATE); @@ -1262,6 +1258,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn, bool new_static = false; bool old_bgp_ready = false; bool new_bgp_ready; + bool is_old_mac_dup = false; /* Check if the MAC exists. */ zmac = zebra_evpn_mac_lookup(zevpn, macaddr); @@ -1408,6 +1405,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn, old_bgp_ready = false; } if (old_zmac) { + is_old_mac_dup = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE); old_mac_seq = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_REMOTE) ? old_zmac->rem_seq @@ -1437,6 +1435,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn, != 0) { old_zmac = n->mac; if (old_zmac) { + is_old_mac_dup = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_DUPLICATE); old_mac_seq = CHECK_FLAG(old_zmac->flags, ZEBRA_MAC_REMOTE) @@ -1499,7 +1498,7 @@ int zebra_evpn_local_neigh_update(struct zebra_evpn *zevpn, /* Check old and/or new MAC detected as duplicate mark * the neigh as duplicate */ - if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) { + if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, is_old_mac_dup, zmac, n)) { flog_warn( EC_ZEBRA_DUP_IP_INHERIT_DETECTED, "VNI %u: MAC %pEA IP %pIA detected as duplicate during local update, inherit duplicate from MAC", @@ -2034,6 +2033,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn, bool do_dad = false; bool is_dup_detect = false; bool is_router; + bool is_old_mac_dup = false; assert(mac); is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); @@ -2086,6 +2086,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn, old_mac = zebra_evpn_mac_lookup(zevpn, &n->emac); if (old_mac) { + is_old_mac_dup = CHECK_FLAG(old_mac->flags, ZEBRA_MAC_DUPLICATE); listnode_delete(old_mac->neigh_list, n); n->mac = NULL; zebra_evpn_deref_ip2mac(zevpn, old_mac); @@ -2128,7 +2129,7 @@ void zebra_evpn_neigh_remote_macip_add(struct zebra_evpn *zevpn, /* Check old or new MAC detected as duplicate, * inherit duplicate flag to this neigh. */ - if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) { + if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, is_old_mac_dup, mac, n)) { flog_warn( EC_ZEBRA_DUP_IP_INHERIT_DETECTED, "VNI %u: MAC %pEA IP %pIA detected as duplicate during remote update, inherit duplicate from MAC",