Skip to content

bgpd: Double-free crash in peer_delete() when freeing hostname after doppelganger peer transfer #20628

@routingrocks

Description

@routingrocks

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

  1. Configure BGP with interface-based (unnumbered) peering

  2. 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

  3. Establish BGP session (wait for session to reach Established state)

  4. Remove the interface neighbor from the peer-group:

       no neighbor swp3 interface peer-group fabric

  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triageNeeds further investigation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions