From 336c48c435ca9d4e66b910e8e5c22b5f48a3cb07 Mon Sep 17 00:00:00 2001 From: zhou-run <166502045+zhou-run@users.noreply.github.com> Date: Sat, 11 May 2024 15:30:38 +0800 Subject: [PATCH] isisd: fix crash when deactivating ISIS adjacency on the interface. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. When the command "no router isis WORD" is executed on the interface, it invokes list_delete_all_node to iterate and release the memory of all nodes in the cirtcuit->u.bc.adjdb[1] linked list. However, the nodes are not unlinked during this traversal process, leading to the call of *list->del to delete the data of the linked list nodes. 2. For ISIS, deleting the data of the linked list nodes is done by calling isis_delete_adj. Subsequently, isis_level2_adj_up will be called to iterate and query the cirtcuit->u.bc.adjdb[1] linked list. If there are many neighbors on this interface, accessing the memory of the released linked list nodes may occur. 3. Not limited to ISIS, if the linked list is not unlinked during the deletion of all nodes in process 1, *list->del should not be allowed to iterate through the list again. The backtrace is as follows: (gdb) bt at isisd/isis_csm.c:196 context=) at lib/northbound.c:1131 errmsg_len=errmsg_len@entry=8192) at lib/northbound.c:1356 at lib/northbound.c:1473 errmsg=errmsg@entry=0x7ffc0ced38d0 "", errmsg_len=errmsg_len@entry=8192) at lib/northbound.c:906 comment=comment@entry=0x0, transaction_id=transaction_id@entry=0x0, errmsg=errmsg@entry=0x7ffc0ced38d0 "", errmsg_len=8192) at lib/northbound.c:938 filter=FILTER_RELAXED) at lib/command.c:971 at lib/command.c:1030 vtysh=vtysh@entry=0) at lib/command.c:1198 (gdb) f 3 423 isisd/isis_lsp.c: No such file or directory. (gdb) p node $1 = (struct listnode *) 0x110 (gdb) f 8 316 lib/linklist.c: No such file or directory. (gdb) p list->head->data $2 = (void *) 0x5647f7cabf20 (gdb) p list->head->next->data $3 = (void *) 0x5647f7c9bb60 (gdb) p list->head->next->next->data Cannot access memory at address 0x120 (gdb) p list->head->next->next $4 = (struct listnode *) 0x110 The backtrace provided above pertains to version 8.2.2, but it seems that the same issue exists in the code of the master branch as well. isis_reset_attach_bit() is useless because lsp_handle_adj_state_change() unconditionally calls lsp_regenerate_schedule. Signed-off-by: zhou-run <166502045+zhou-run@users.noreply.github.com> --- isisd/isis_lsp.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 9d671137e945..6cdce80c1ed8 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -442,47 +442,6 @@ void set_overload_on_start_timer(struct event *thread) isis_area_overload_bit_set(area, false); } -static void isis_reset_attach_bit(struct isis_adjacency *adj) -{ - struct isis_area *area = adj->circuit->area; - struct lspdb_head *head; - struct isis_lsp *lsp; - uint8_t lspid[ISIS_SYS_ID_LEN + 2]; - - /* - * If an L2 adjacency changed its state in L-1-2 area, we have to: - * - set the attached bit in L1 LSPs if it's the first L2 adjacency - * - remove the attached bit in L1 LSPs if it's the last L2 adjacency - */ - - if (area->is_type != IS_LEVEL_1_AND_2 || adj->level == ISIS_ADJ_LEVEL1) - return; - - if (!area->attached_bit_send) - return; - - head = &area->lspdb[IS_LEVEL_1 - 1]; - memset(lspid, 0, ISIS_SYS_ID_LEN + 2); - memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN); - - lsp = lsp_search(head, lspid); - if (!lsp) - return; - - if (adj->adj_state == ISIS_ADJ_UP - && !(lsp->hdr.lsp_bits & LSPBIT_ATT)) { - sched_debug("ISIS (%s): adj going up regenerate lsp-bits", - area->area_tag); - lsp_regenerate_schedule(area, IS_LEVEL_1, 0); - } else if (adj->adj_state == ISIS_ADJ_DOWN - && (lsp->hdr.lsp_bits & LSPBIT_ATT) - && !isis_level2_adj_up(area)) { - sched_debug("ISIS (%s): adj going down regenerate lsp-bits", - area->area_tag); - lsp_regenerate_schedule(area, IS_LEVEL_1, 0); - } -} - static uint8_t lsp_bits_generate(int level, int overload_bit, int attached_bit, struct isis_area *area) { @@ -2357,7 +2316,6 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj) /* when an adjacency state changes determine if we need to * change attach_bits in other area's LSPs */ - isis_reset_attach_bit(adj); return 0; }