-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Description
Issue:
BGPd crashes with a double-free when deleting interface BGP neighbors that are part of a peer-group.
Crash seen in in peer_delete() at the XFREE(MTYPE_BGP_PEER_HOST, peer->hostname) call.
Potential Rootcause:
In peer_xfer_conn() (bgpd/bgp_fsm.c), the hostname, domainname, and soft_version pointers are transferred between peers using simple pointer assignment:
if (from_peer->hostname != NULL) {
peer->hostname = from_peer->hostname;
from_peer->hostname = NULL;
}
where both peers can reference the same memory if the transfer doesn't complete cleanly or if there's a race condition during peer state transitions. When both peers are eventually deleted, the same memory is freed twice, causing the crash.
Backtrace:
#0 0x00007fc88b41aeec in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007fc88b3cbfb2 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007fc88b70045c in core_handler (signo=11, siginfo=0x7fffbdee6c30, context=<optimized out>) at ../lib/sigevent.c:261
#3 <signal handler called>
#4 0x00007fc88b429d49 in malloc_usable_size () from /lib/x86_64-linux-gnu/libc.so.6
#5 0x00007fc88b6c99f9 in mt_count_free (ptr=0x55ff594d9320, mt=0x55ff25046460 <MTYPE_BGP_PEER_HOST>) at ../lib/memory.c:77
#6 qfree (mt=0x55ff25046460 <MTYPE_BGP_PEER_HOST>, ptr=0x55ff594d9320) at ../lib/memory.c:129
#7 0x000055ff24eac802 in peer_delete (peer=peer@entry=0x55ff5941d770) at ../bgpd/bgpd.c:2864
#8 0x000055ff24e65982 in no_neighbor_interface_config (...) at ../bgpd/bgp_vty.c:5862
#9 0x00007fc88b695ab0 in cmd_execute_command_real (...) at ../lib/command.c:1018
#10 0x00007fc88b695bae in cmd_execute_command (...) at ../lib/command.c:1076
#11 0x00007fc88b695e40 in cmd_execute (vty=..., cmd="no neighbor swp3 interface peer-group test_gr_shut", ...) at ../lib/command.c:1243
Version
10.0.3
How to reproduce
The issue is not consistently reproducible. It is seen intermittently under the below condition
-
Configure BGP with interface-based (unnumbered) peering
-
Create a peer-group and assign interface neighbors to it:
router bgp 65001
neighbor fabric peer-group
neighbor swp3 interface peer-group fabric
neighbor swp3 remote-as external
-
Establish BGP session (wait for session to reach Established state)
-
Remove the interface neighbor from the peer-group:
no neighbor swp3 interface peer-group fabric
-
Crash may seen during the peer_delete() call
Expected behavior
No crash
Actual behavior
Crash
Additional context
--- a/bgpd/bgp_fsm.c
Potential fix :
+++ b/bgpd/bgp_fsm.c
@@ -242,8 +242,7 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
peer->hostname = NULL;
}
if (from_peer->hostname != NULL) {
- peer->hostname = from_peer->hostname;
- from_peer->hostname = NULL;
+ peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, from_peer->hostname);
}
if (peer->domainname) {
@@ -251,8 +250,7 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
peer->domainname = NULL;
}
if (from_peer->domainname != NULL) {
- peer->domainname = from_peer->domainname;
- from_peer->domainname = NULL;
+ peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, from_peer->domainname);
}
if (peer->soft_version) {
@@ -260,8 +258,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
peer->soft_version = NULL;
}
if (from_peer->soft_version) {
- peer->soft_version = from_peer->soft_version;
- from_peer->soft_version = NULL;
+ peer->soft_version = XSTRDUP(MTYPE_BGP_SOFT_VERSION,
+ from_peer->soft_version);
}
Checklist
- I have searched the open issues for this bug.
- I have not included sensitive information in this report.