Commit dbe6718f0e for frr

commit dbe6718f0ee4dd2f71aa4b99fe32883737c812b8
Author: Donatas Abraitis <donatas@opensourcerouting.org>
Date:   Tue Sep 29 11:25:41 2026 +0300

    bgpd: Give a hint for Coverity about BGP_DEST_AUTOUNLOCK

    Each bgp_node_match() call takes its own lock. When dest1 == dest2, the node
    has picked up two extra locks, one per call, on top of whatever the table
    already holds.

    Coverity treats bgp_dest_unlock_node() as a function that may free,
    because of its rn->lock == 1 branch. It doesn't track the counter, so once
    it sees two pointers to the same node, it assumes the first unlock freed
    it and reports the second as a use-after-free.

    Signed-off-by: Donatas Abraitis <donatas@opensourcerouting.org>

diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 87f0096a48..ea8a7a6392 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -627,6 +627,7 @@ bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer)

 	ret = (dest1 == dest2);

+	/* coverity[double_free] - aliased dest, locked by each bgp_node_match() */
 	return ret;
 }

@@ -655,6 +656,7 @@ bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)

 	ret = (dest1 == dest2);

+	/* coverity[double_free] - aliased dest, locked by each bgp_node_match() */
 	return ret;
 }

@@ -689,6 +691,7 @@ bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
 		dest2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
 		if (dest1 == dest2) {
 			bgp_dest_unlock_node(dest2);
+			/* coverity[double_free] - aliased dest, locked by each bgp_node_match() */
 			return true;
 		}

@@ -731,6 +734,7 @@ bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
 		dest2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
 		if (dest1 == dest2) {
 			bgp_dest_unlock_node(dest2);
+			/* coverity[double_free] - aliased dest, locked by each bgp_node_match() */
 			return true;
 		}