mirror_frr/isisd
zhou-run 5658142ebc isisd: fix crash when calculating the neighbor spanning tree based on the fragmented LSP
1. When the root IS regenerates an LSP, it calls lsp_build() -> lsp_clear_data() to free the TLV memory of the first fragment and all other fragments. If the number of fragments in the regenerated LSP decreases or if no fragmentation is needed, the extra LSP fragments are not immediately deleted. Instead, lsp_seqno_update() -> lsp_purge() is called to set the remaining time to zero and start aging, while also notifying other IS nodes to age these fragments. lsp_purge() usually does not reset lsp->hdr.seqno to zero because the LSP might recover during the aging process.
2. When other IS nodes receive an LSP, they always call process_lsp() -> isis_unpack_tlvs() to allocate TLV memory for the LSP. This does not differentiate whether the received LSP has a remaining lifetime of zero. Therefore, it is rare for an LSP of a non-root IS to have empty TLVs. Of course, if an LSP with a remaining time of zero and already corrupted is received, lsp_update() -> lsp_purge() will be called to free the TLV memory of the LSP, but this scenario is rare.
3. In LFA calculations, neighbors of the root IS are traversed, and each neighbor is taken as a new root to compute the neighbor SPT. During this process, the old root IS will serve as a neighbor of the new root IS, triggering a call to isis_spf_process_lsp() to parse the LSP of the old root IS and obtain its IP vertices and neighboring IS vertices. However, isis_spf_process_lsp() only checks whether the TLVs in the first fragment of the LSP exist, and does not check the TLVs in the fragmented LSP. If the TLV memory of the fragmented LSP of the old root IS has been freed, it can lead to a null pointer access, causing the current crash.

Additionally, for the base SPT, there are only two places where the LSP of the root IS is parsed:
1. When obtaining the UP neighbors of the root IS via spf_adj_list_parse_lsp().
2. When preloading the IP vertices of the root IS via isis_lsp_iterate_ip_reach().
Both of these checks ensure that frag->tlvs is not null, and they do not subsequently call isis_spf_process_lsp() to parse the root IS's LSP. It is very rare for non-root IS LSPs to have empty TLVs unless they are corrupted LSPs awaiting deletion. If it happens, a crash will occur.

The backtrace is as follows:
(gdb) bt
#0  0x00007f3097281fe1 in raise () from /lib/x86_64-linux-gnu/libpthread.so.0
#1  0x00007f30973a2972 in core_handler (signo=11, siginfo=0x7ffce66c2870, context=0x7ffce66c2740) at ../lib/sigevent.c:261
#2  <signal handler called>
#3  0x000055dfa805512b in isis_spf_process_lsp (spftree=0x55dfa950eee0, lsp=0x55dfa94cb590, cost=10, depth=1, root_sysid=0x55dfa950ef6c "", parent=0x55dfa952fca0)
    at ../isisd/isis_spf.c:898
#4  0x000055dfa805743b in isis_spf_loop (spftree=0x55dfa950eee0, root_sysid=0x55dfa950ef6c "") at ../isisd/isis_spf.c:1688
#5  0x000055dfa805784f in isis_run_spf (spftree=0x55dfa950eee0) at ../isisd/isis_spf.c:1808
#6  0x000055dfa8037ff5 in isis_spf_run_neighbors (spftree=0x55dfa9474440) at ../isisd/isis_lfa.c:1259
#7  0x000055dfa803ac17 in isis_spf_run_lfa (area=0x55dfa9477510, spftree=0x55dfa9474440) at ../isisd/isis_lfa.c:2300
#8  0x000055dfa8057964 in isis_run_spf_with_protection (area=0x55dfa9477510, spftree=0x55dfa9474440) at ../isisd/isis_spf.c:1827
#9  0x000055dfa8057c15 in isis_run_spf_cb (thread=0x7ffce66c38e0) at ../isisd/isis_spf.c:1889
#10 0x00007f30973bbf04 in thread_call (thread=0x7ffce66c38e0) at ../lib/thread.c:1990
#11 0x00007f309735497b in frr_run (master=0x55dfa91733c0) at ../lib/libfrr.c:1198
#12 0x000055dfa8029d5d in main (argc=5, argv=0x7ffce66c3b08, envp=0x7ffce66c3b38) at ../isisd/isis_main.c:273
(gdb) f 3
#3  0x000055dfa805512b in isis_spf_process_lsp (spftree=0x55dfa950eee0, lsp=0x55dfa94cb590, cost=10, depth=1, root_sysid=0x55dfa950ef6c "", parent=0x55dfa952fca0)
    at ../isisd/isis_spf.c:898
898     ../isisd/isis_spf.c: No such file or directory.
(gdb) p te_neighs
$1 = (struct isis_item_list *) 0x120
(gdb) p lsp->tlvs
$2 = (struct isis_tlvs *) 0x0
(gdb) p lsp->hdr
$3 = {pdu_len = 27, rem_lifetime = 0, lsp_id = "\000\000\000\000\000\001\000\001", seqno = 4, checksum = 59918, lsp_bits = 1 '\001'}

The backtrace provided above pertains to version 8.5.4, but it seems that the same issue exists in the code of the master branch as well.

I have reviewed the process for calculating the SPT based on the LSP, and isis_spf_process_lsp() is the only function that does not check whether the TLVs in the fragments are empty. Therefore, I believe that modifying this function alone should be sufficient. If the TLVs of the current fragment are already empty, we do not need to continue processing subsequent fragments. This is consistent with the behavior where we do not process fragments if the TLVs of the first fragment are empty.
Of course, one could argue that lsp_purge() should still retain the TLV memory, freeing it and then reallocating it if needed. However, this is a debatable point because in some scenarios, it is permissible for the LSP to have empty TLVs. For example, after receiving an SNP (Sequence Number PDU) message, an empty LSP (with lsp->hdr.seqno = 0) might be created by calling lsp_new. If the corresponding LSP message is discarded due to domain or area authentication failure, the TLV memory wouldn't be allocated.

Test scenario:
In an LFA network, importing a sufficient number of static routes to cause LSP fragmentation, and then rolling back the imported static routes so that the LSP is no longer fragmented, can easily result in this issue.

Signed-off-by: zhou-run <zhou.run@h3c.com>
(cherry picked from commit e905177a8c)
2024-07-16 14:08:00 +00:00
..
.gitignore *: cleanup .gitignore files 2018-09-08 21:30:42 +02:00
AUTHORS Add support of Traffic Engineering to IS-IS 2016-09-03 11:05:50 -04:00
fabricd.c isisd: update struct isis_spftree with algorithm id 2023-04-17 11:06:08 +02:00
fabricd.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_adjacency.c isisd: Extend IS-IS adjacency with SRv6 adj SIDs 2023-09-11 22:11:48 +02:00
isis_adjacency.h isisd: Add support for SRv6 Adjacency SIDs 2023-09-11 22:11:47 +02:00
isis_affinitymap.c isisd: fix potential null pointer in isis_affinity_map_update() 2023-04-20 16:23:50 +02:00
isis_affinitymap.h isisd: add affinity-map configuration hooks 2023-04-18 11:33:15 +02:00
isis_bfd.c *: Convert struct event_master to struct event_loop 2023-03-24 08:32:17 -04:00
isis_bfd.h *: Convert struct event_master to struct event_loop 2023-03-24 08:32:17 -04:00
isis_bpf.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_circuit.c isisd: Make SRv6 interface configurable 2023-09-11 22:11:51 +02:00
isis_circuit.h *: Rename struct thread to struct event 2023-03-24 08:32:17 -04:00
isis_cli.c isisd: Make SRv6 interface configurable 2023-09-11 22:11:51 +02:00
isis_common.h isisd: Update to the new printfrr ISO format 2023-03-21 15:21:47 +01:00
isis_constants.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_csm.c *: Convert event.h to frrevent.h 2023-03-24 08:32:17 -04:00
isis_csm.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_dlpi.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_dr.c *: Convert event.h to frrevent.h 2023-03-24 08:32:17 -04:00
isis_dr.h *: Rename struct thread to struct event 2023-03-24 08:32:17 -04:00
isis_dynhn.c Merge pull request #12698 from Orange-OpenSource/isisd 2023-04-11 09:49:01 -04:00
isis_dynhn.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_errors.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_errors.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_events.c Merge pull request #12698 from Orange-OpenSource/isisd 2023-04-11 09:49:01 -04:00
isis_events.h *: Rename struct thread to struct event 2023-03-24 08:32:17 -04:00
isis_flags.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_flags.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_flex_algo.c Revert "lib: add a frr_each_const macro" 2023-09-07 12:08:50 +02:00
isis_flex_algo.h isisd: calculate flex-algo constraint spf 2023-04-18 11:33:15 +02:00
isis_ldp_sync.c *: Convert event.h to frrevent.h 2023-03-24 08:32:17 -04:00
isis_ldp_sync.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_lfa.c isisd: add support of (ti-)lfa to flex-algo 2023-04-18 11:33:15 +02:00
isis_lfa.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_lsp.c isisd: Fix dislaying LSP ID 2023-12-05 09:12:45 +00:00
isis_lsp.h *: Rename struct thread to struct event 2023-03-24 08:32:17 -04:00
isis_main.c isisd: Add function to terminate the SRv6 module 2023-08-04 09:29:16 +02:00
isis_misc.c isisd: replace gmtime with gmtime_r 2023-07-10 17:06:17 -04:00
isis_misc.h isisd: Update to the new printfrr ISO format 2023-03-21 15:21:47 +01:00
isis_mt.c isisd: Update to the new printfrr ISO format 2023-03-21 15:21:47 +01:00
isis_mt.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_nb_config.c isisd: remove redundant northbound destroy callbacks 2023-10-06 17:37:41 +03:00
isis_nb_notifications.c isisd: Update to the new printfrr ISO format 2023-03-21 15:21:47 +01:00
isis_nb_state.c isisd: Update to the new printfrr ISO format 2023-03-21 15:21:47 +01:00
isis_nb.c isisd: remove redundant northbound destroy callbacks 2023-10-06 17:37:41 +03:00
isis_nb.h isisd: remove redundant northbound destroy callbacks 2023-10-06 17:37:41 +03:00
isis_network.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_pdu_counter.c isisd: Add log-pdu-drops log functionality 2023-04-04 09:23:21 -07:00
isis_pdu_counter.h isisd: Add log-pdu-drops log functionality 2023-04-04 09:23:21 -07:00
isis_pdu.c Merge pull request #13163 from isabelladeleon12/isis_log_drops 2023-04-11 09:55:24 -04:00
isis_pdu.h isisd: Add log-pdu-drops log functionality 2023-04-04 09:23:21 -07:00
isis_pfpacket.c isisd: pfpacket BPF filter with IS-IS over tunnel support 2023-03-12 16:15:27 +01:00
isis_redist.c isisd: add the 'redistribute table' internal support 2023-07-12 14:06:00 +02:00
isis_redist.h isisd: add the 'redistribute table' internal support 2023-07-12 14:06:00 +02:00
isis_route.c isisd: fix merging flex-algo route nodes 2023-04-18 11:33:15 +02:00
isis_route.h isisd: merge algorithm tables 2023-04-18 11:33:15 +02:00
isis_routemap.c *: Convert event.h to frrevent.h 2023-03-24 08:32:17 -04:00
isis_routemap.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_snmp.c Merge pull request #12698 from Orange-OpenSource/isisd 2023-04-11 09:49:01 -04:00
isis_spf_private.h isisd: calculate flex-algo constraint spf 2023-04-18 11:33:15 +02:00
isis_spf.c isisd: fix crash when calculating the neighbor spanning tree based on the fragmented LSP 2024-07-16 14:08:00 +00:00
isis_spf.h isisd: add option to display isis routes as json 2023-04-18 11:33:15 +02:00
isis_sr.c isisd: update Node-SID flag dynamically 2023-07-29 14:18:39 -03:00
isis_sr.h isisd: update Node-SID flag dynamically 2023-07-29 14:18:39 -03:00
isis_srv6.c isisd: Fix style warnings reported by CI 2023-11-05 21:40:07 +00:00
isis_srv6.h isisd: Fix openfabric crash 2023-11-05 21:40:06 +00:00
isis_te.c Merge pull request #12933 from Orange-OpenSource/link_state 2023-04-20 18:33:21 +02:00
isis_te.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_tlvs.c isisd: fix ip/ipv6 reachability tlvs 2024-05-13 08:12:22 +00:00
isis_tlvs.h isisd: Add support for SRv6 Adjacency SIDs 2023-09-11 22:11:47 +02:00
isis_tx_queue.c Merge pull request #12698 from Orange-OpenSource/isisd 2023-04-11 09:49:01 -04:00
isis_tx_queue.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_vty_fabricd.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
isis_zebra.c isisd: Fix SRv6 memory leaks 2023-09-21 18:43:04 +02:00
isis_zebra.h isisd: Add functions to install/remove adj SIDs 2023-09-11 22:11:47 +02:00
isisd.c isisd: Make SRv6 Node MSDs customizable 2023-09-11 22:11:50 +02:00
isisd.h isisd: Add YANG path for SRv6 2023-08-04 09:29:15 +02:00
iso_checksum.c *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
iso_checksum.h *: auto-convert to SPDX License IDs 2023-02-09 14:09:11 +01:00
Makefile build: non-recursive isisd 2017-08-04 11:09:50 +02:00
README More cleanup in isisd. 2005-01-01 21:12:56 +00:00
subdir.am isisd: staticd: need to link directly against libyang 2023-10-27 09:57:02 +00:00

Constraints

  o Maximum number of interfaces 255