Skip to content

Commit

Permalink
isisd: fix crash when deactivating ISIS adjacency on the interface.
Browse files Browse the repository at this point in the history
1. When the command "no <ip|ipv6> 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=<optimized out>) 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>
  • Loading branch information
zhou-run authored and baozhen-H3C committed May 28, 2024
1 parent b3600d8 commit 336c48c
Showing 1 changed file with 0 additions and 42 deletions.
42 changes: 0 additions & 42 deletions isisd/isis_lsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 336c48c

Please sign in to comment.