bgpd: fix crash on daemon exit

Don't attempt to send BFD daemon a message to remove the peer
registration on daemon exit, otherwise we'll access a dangling
interface pointer and we'll crash.

This crash was not previosly possible because the function that built
the message was passing the interface pointer but not using it due to
the exit condition.

In `lib/bfd.c`:

```
void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info,
		      int family, void *dst_ip, void *src_ip, char *if_name,
		      int ttl, int multihop, int cbit, int command,
		      int set_flag, vrf_id_t vrf_id)
{
	struct bfd_session_arg args = {};
	size_t addrlen;

	/* Individual reg/dereg messages are suppressed during shutdown. */
	if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) {
		if (bfd_debug)
			zlog_debug(
				"%s: Suppressing BFD peer reg/dereg messages",
				__func__);
		return;
	}
```

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
This commit is contained in:
Rafael Zalamena 2020-05-21 16:02:44 -03:00
parent 68286f9619
commit 95a99382cb

View File

@ -101,6 +101,19 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command)
vrf_id_t vrf_id;
size_t addrlen;
/*
* XXX: some pointers are dangling during shutdown, so instead of
* trying to send a message during signal handlers lets just wait BGP
* to terminate zebra's connection and BFD will automatically find
* out that we are no longer expecting notifications.
*
* The pointer that is causing a crash here is `peer->nexthop.ifp`.
* That happens because at this point of the shutdown all interfaces are
* already `free()`d.
*/
if (bm->terminating)
return;
bfd_info = (struct bfd_info *)peer->bfd_info;
vrf_id = peer->bgp->vrf_id;