]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: fix backlink check
authorChristian Hopps <chopps@labn.net>
Fri, 9 Jul 2021 07:58:02 +0000 (03:58 -0400)
committerChristian Hopps <chopps@labn.net>
Fri, 9 Jul 2021 08:15:34 +0000 (04:15 -0400)
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 <chopps@labn.net>
ospf6d/ospf6_spf.c

index 032484e28885aae9b6dadb19e109b73dee4c5aa3..051b3a63efa6ba9879b7d0531658e798cace262c 100644 (file)
@@ -225,21 +225,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)