From 712aaf03f82046e868e464ea1ea5323108a3a303 Mon Sep 17 00:00:00 2001 From: Claudio Jeker Date: Tue, 29 Oct 2019 06:42:06 +0000 Subject: Fix two cases where the nexthop_runners tail queue can get corrupted. First by requeuing an element that is already on the list and second by freeing a nexthop that is still on the list resulting in a use after free. This should fix bgpd crashes seen by various people. Problem report including backtrace from benno@ OK benno@ --- usr.sbin/bgpd/rde_rib.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'usr.sbin/bgpd') diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 9dd2d233060..b3d444f4751 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.207 2019/09/27 14:50:39 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.208 2019/10/29 06:42:05 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker @@ -1777,13 +1777,15 @@ nexthop_update(struct kroute_nexthop *msg) if (nexthop_unref(nh)) return; /* nh lost last ref, no work left */ - if (nh->next_prefix) + if (nh->next_prefix) { /* * If nexthop_runner() is not finished with this nexthop * then ensure that all prefixes are updated by setting * the oldstate to NEXTHOP_FLAPPED. */ nh->oldstate = NEXTHOP_FLAPPED; + TAILQ_REMOVE(&nexthop_runners, nh, runner_l); + } if (msg->connected) { nh->flags |= NEXTHOP_CONNECTED; @@ -1855,8 +1857,12 @@ nexthop_unlink(struct prefix *p) if (p->nexthop == NULL || (p->flags & PREFIX_NEXTHOP_LINKED) == 0) return; - if (p == p->nexthop->next_prefix) + if (p == p->nexthop->next_prefix) { p->nexthop->next_prefix = LIST_NEXT(p, entry.list.nexthop); + /* remove nexthop from list if no prefixes left to update */ + if (p->nexthop->next_prefix == NULL) + TAILQ_REMOVE(&nexthop_runners, p->nexthop, runner_l); + } p->flags &= ~PREFIX_NEXTHOP_LINKED; LIST_REMOVE(p, entry.list.nexthop); -- cgit v1.2.3