From 93bdc367576d15fbec935e01cac3517aa76e6ef6 Mon Sep 17 00:00:00 2001 From: Emanuele Di Pascale Date: Thu, 29 Oct 2020 09:51:27 +0100 Subject: [PATCH] isisd: fix segfault in the circuit p2p/bcast union The fields in the broadcast/p2p union struct in an isis circuit are initialized when the circuit goes up, but currently this step is skipped if the interface is passive. This can create problems if the circuit type (referred to as network type in the config) changes from broadcast to point-to-point. We can end up with the p2p neighbor pointer pointing at some garbage left by the broadcast struct in the union, which would then cause a segfault the first time we would dereference it - for example when building the lsp, or computing the SPF tree. compressed backtrace of a possible crash: #0 0x0000555555579a9c in lsp_build at frr/isisd/isis_lsp.c:1114 #1 0x000055555557a516 in lsp_regenerate at frr/isisd/isis_lsp.c:1301 #2 0x000055555557aa25 in lsp_refresh at frr/isisd/isis_lsp.c:1381 #3 0x00007ffff7b2622c in thread_call at frr/lib/thread.c:1549 #4 0x00007ffff7ad6df4 in frr_run at frr/lib/libfrr.c:1098 #5 0x000055555556b67f in main at frr/isisd/isis_main.c:272 isis_lsp.c: 1112 case CIRCUIT_T_P2P: { 1113 struct isis_adjacency *nei = circuit->u.p2p.neighbor; 1114 if (nei && nei->adj_state == ISIS_ADJ_UP Signed-off-by: Emanuele Di Pascale --- isisd/isis_circuit.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 730d224cb..e3c70264f 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -598,8 +598,20 @@ int isis_circuit_up(struct isis_circuit *circuit) if (circuit->state == C_STATE_UP) return ISIS_OK; - if (circuit->is_passive) + if (circuit->is_passive) { + /* make sure the union fields are initialized, else we + * could end with garbage values from a previous circuit + * type, which would then cause a segfault when building + * LSPs or computing the SPF tree + */ + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + circuit->u.bc.adjdb[0] = list_new(); + circuit->u.bc.adjdb[1] = list_new(); + } else if (circuit->circ_type == CIRCUIT_T_P2P) { + circuit->u.p2p.neighbor = NULL; + } return ISIS_OK; + } if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) { flog_err( -- 2.39.2