From 0ad648b5e5c5a436ce0c074e5cd0ccf42b58edc2 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Fri, 9 Jul 2021 03:58:02 -0400 Subject: [PATCH] ospf6d: fix backlink check This code has been wrong ~ever (according to git history). There are 3 conditional blocks with the added assertion that both the LSA and the vertex being checked can't both be network LSAs. The third block is clearly assuming both LSA and vertex are router LSAs b/c it is accessing the backlink and lsdesc as router lsdesc's also making sure both are p2p links (which they would have to be to point at each other). The programming error here is that (A && B) == False does NOT imply !A, but the code is written that way. So we end up in the third block one of LSA or vertex being network LSAs rather easily (whenever that is the case and the desc isn't the backlink being sought). This was caught by ASAN b/c the lsdesc and backlinks are being accessed (> 4 byte field offsets) as if they were router lsdesc's in the third block, when in fact one of them is a network lsdesc which is only 4 bytes long -- so ASAN flags the access beyond bounds. Signed-off-by: Christian Hopps (cherry picked from commit ff2052eefc7d99604c4480398c86163f2255ff73) --- ospf6d/ospf6_spf.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 7652d71c59..803fc4c640 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -223,21 +223,25 @@ static char *ospf6_lsdesc_backlink(struct ospf6_lsa *lsa, caddr_t lsdesc, assert(!(OSPF6_LSA_IS_TYPE(NETWORK, lsa) && VERTEX_IS_TYPE(NETWORK, v))); - if (OSPF6_LSA_IS_TYPE(NETWORK, lsa) - && NETWORK_LSDESC_GET_NBR_ROUTERID(backlink) - == v->lsa->header->adv_router) - found = backlink; - else if (VERTEX_IS_TYPE(NETWORK, v) - && ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, backlink) - && ROUTER_LSDESC_GET_NBR_ROUTERID(backlink) - == v->lsa->header->adv_router - && ROUTER_LSDESC_GET_NBR_IFID(backlink) - == ntohl(v->lsa->header->id)) - found = backlink; - else { + if (OSPF6_LSA_IS_TYPE(NETWORK, lsa)) { + if (NETWORK_LSDESC_GET_NBR_ROUTERID(backlink) + == v->lsa->header->adv_router) + found = backlink; + } else if (VERTEX_IS_TYPE(NETWORK, v)) { + if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, backlink) + && ROUTER_LSDESC_GET_NBR_ROUTERID(backlink) + == v->lsa->header->adv_router + && ROUTER_LSDESC_GET_NBR_IFID(backlink) + == ntohl(v->lsa->header->id)) + found = backlink; + } else { + assert(OSPF6_LSA_IS_TYPE(ROUTER, lsa) + && VERTEX_IS_TYPE(ROUTER, v)); + if (!ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, backlink) || !ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) continue; + if (ROUTER_LSDESC_GET_NBR_IFID(backlink) != ROUTER_LSDESC_GET_IFID(lsdesc) || ROUTER_LSDESC_GET_NBR_IFID(lsdesc) -- 2.39.5