Skip to content

Commit

Permalink
isisd: fix segfault in the circuit p2p/bcast union
Browse files Browse the repository at this point in the history
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 <emanuele@voltanet.io>
  • Loading branch information
edipascale authored and idryzhov committed Nov 17, 2020
1 parent 9125241 commit fe38421
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion isisd/isis_circuit.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,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(
Expand Down

0 comments on commit fe38421

Please sign in to comment.