]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: fix infinite loop when parsing LSPs
authorLouis Scalbert <louis.scalbert@6wind.com>
Fri, 27 May 2022 08:42:53 +0000 (10:42 +0200)
committerMergify <37929162+mergify[bot]@users.noreply.github.com>
Tue, 5 Jul 2022 13:48:39 +0000 (13:48 +0000)
Fixing the crash:

> #0  0x0000560aa80f8e30 in lspdb_const_find (h=<error reading variable: Cannot access memory at address 0x7fff5e95efe8>, item=<error reading variable: Cannot access memory at address 0x7fff5e95efe0>) at ./isisd/isis_lsp.h:64
> #1  0x0000560aa80f8e9d in lspdb_find (h=0x560aaa1ed3b8, item=0x7fff5e95f050) at ./isisd/isis_lsp.h:64
> #2  0x0000560aa80f92f9 in lsp_search (head=0x560aaa1ed3b8, id=0x7fff5e95f200 "") at isisd/isis_lsp.c:100
> #3  0x0000560aa8113d69 in spf_adj_list_parse_tlv (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, id=0x560aad331a78 "", desig_is_id=0x0, pseudo_metric=0, metric=3, oldmetric=false, subtlvs=0x0) at isisd/isis_spf.c:1330
> #4  0x0000560aa811419d in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1f4e50, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1429
> #5  0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1ff8e0, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> #6  0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1f4e50, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> (...)
> #65507 0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1ff8e0, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> #65508 0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1f4e50, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> #65509 0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1ff8e0, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> #65510 0x0000560aa81141fe in spf_adj_list_parse_lsp (spftree=0x560aaa1f09d0, adj_list=0x560aaa214480, lsp=0x560aaa1f4e50, pseudo_nodeid=0x0, pseudo_metric=0) at isisd/isis_spf.c:1442
> #65511 0x0000560aa8114313 in isis_spf_build_adj_list (spftree=0x560aaa1f09d0, lsp=0x560aaa1f4e50) at isisd/isis_spf.c:1455
> #65512 0x0000560aa8114f09 in isis_run_spf (spftree=0x560aaa1f09d0) at isisd/isis_spf.c:1775
> #65513 0x0000560aa8115057 in isis_run_spf_with_protection (area=0x560aaa1ed3b0, spftree=0x560aaa1f09d0) at isisd/isis_spf.c:1801
> #65514 0x0000560aa8115311 in isis_run_spf_cb (thread=0x7fff5f15e5a0) at isisd/isis_spf.c:1859
> #65515 0x00007f90bac66dcc in thread_call (thread=0x7fff5f15e5a0) at lib/thread.c:2002
> #65516 0x00007f90bac013ee in frr_run (master=0x560aa9f5cb40) at lib/libfrr.c:1196
> #65517 0x0000560aa80e7da2 in main (argc=2, argv=0x7fff5f15e7b8, envp=0x7fff5f15e7d0) at isisd/isis_main.c:273

The fix is similar to the crash fix included in d9884a758c
("isisd: Prepare IS-IS for Link State support"). The fix was:

> diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
> index 94353a5bc8..92d329f035 100644
> --- a/isisd/isis_lsp.c
> +++ b/isisd/isis_lsp.c
> @@ -2166,7 +2178,7 @@ int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid,
>   if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0)
>   return LSP_ITER_CONTINUE;
>
> - /* Parse main LSP. */
> + /* Parse LSP */
>   if (lsp->tlvs) {
>   if (!fabricd && !pseudo_lsp && family == AF_INET
>       && mtid == ISIS_MT_IPV4_UNICAST) {
> @@ -2236,13 +2248,17 @@ int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid,
>   }
>   }
>
> - /* Parse LSP fragments. */
> - for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
> - if (!frag->tlvs)
> - continue;
> + /* Parse LSP fragments if it is not a fragment itself */
> + if (!LSP_FRAGMENT(lsp->hdr.lsp_id))
> + for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
> + if (!frag->tlvs)
> + continue;
>
> - isis_lsp_iterate_ip_reach(frag, family, mtid, cb, arg);
> - }
> + if (isis_lsp_iterate_ip_reach(frag, family, mtid, cb,
> +       arg)
> +     == LSP_ITER_STOP)
> + return LSP_ITER_STOP;
> + }
>
>   return LSP_ITER_CONTINUE;
>  }

Fixes: 7b36d36e0e ("isisd: make the SPF code more modular")
Fixes: 5e56a50559 ("isisd: fix infinite loop when parsing LSPs")
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
(cherry picked from commit 8c8a5a02fa66523a96142083575e1eb7b0033667)

isisd/isis_spf.c

index 2d792a9c75ea5879f833fccb55f6a88a59c5b089..3aef8ada24bf831a873f868e271d299b37c5de44 100644 (file)
@@ -1414,7 +1414,7 @@ static void spf_adj_list_parse_lsp(struct isis_spftree *spftree,
        if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0)
                return;
 
-       /* Parse main LSP. */
+       /* Parse LSP. */
        if (lsp->tlvs) {
                if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
                        head = lsp->tlvs->oldstyle_reach.head;
@@ -1446,6 +1446,9 @@ static void spf_adj_list_parse_lsp(struct isis_spftree *spftree,
                }
        }
 
+       if (LSP_FRAGMENT(lsp->hdr.lsp_id))
+               return;
+
        /* Parse LSP fragments. */
        for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
                if (!frag->tlvs)