From e075df3a05397a4623bbe07b63551e458bb89b65 Mon Sep 17 00:00:00 2001 From: Olivier Dugeon Date: Tue, 23 Jun 2020 16:31:55 +0200 Subject: [PATCH] isisd: Segment Routing improve subTLVs parser For Segment Routing, isis_tlvs.c may failed if incorrect or maformed TLVs are sent to the FRR router. This patch improve detection of such subTLVs error and skip them, in particular for SRGB, SRLB and MSD subTLVs. Signed-off-by: Olivier Dugeon --- isisd/isis_tlvs.c | 38 +++++++++++++++++++++++++++++++++----- isisd/isis_tlvs.h | 7 ++++++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index a58038b327..f3c9c47691 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -2744,7 +2744,7 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, uint8_t type; uint8_t length; uint8_t subtlv_len; - uint8_t sid_len; + uint8_t size; sbuf_push(log, indent, "Unpacking Router Capability TLV...\n"); if (tlv_len < ISIS_ROUTER_CAP_SIZE) { @@ -2778,6 +2778,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, length = stream_getc(s); switch (type) { case ISIS_SUBTLV_SID_LABEL_RANGE: + /* Check that SRGB is correctly formated */ + if (length < SUBTLV_RANGE_LABEL_SIZE + || length > SUBTLV_RANGE_INDEX_SIZE) { + stream_forward_getp(s, length); + continue; + } /* Only one SRGB is supported. Skip subsequent one */ if (rcap->srgb.range_size != 0) { stream_forward_getp(s, length); @@ -2787,8 +2793,8 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, rcap->srgb.range_size = stream_get3(s); /* Skip Type and get Length of SID Label */ stream_getc(s); - sid_len = stream_getc(s); - if (sid_len == ISIS_SUBTLV_SID_LABEL_SIZE) + size = stream_getc(s); + if (size == ISIS_SUBTLV_SID_LABEL_SIZE) rcap->srgb.lower_bound = stream_get3(s); else rcap->srgb.lower_bound = stream_getl(s); @@ -2802,6 +2808,10 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, rcap->srgb.lower_bound = 0; rcap->srgb.range_size = 0; } + /* Only one range is supported. Skip subsequent one */ + size = length - (size + SUBTLV_SR_BLOCK_SIZE); + if (size > 0) + stream_forward_getp(s, length); break; case ISIS_SUBTLV_ALGORITHM: /* Only 2 algorithms are supported: SPF & Strict SPF */ @@ -2814,6 +2824,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, s, length - SR_ALGORITHM_COUNT); break; case ISIS_SUBTLV_SRLB: + /* Check that SRLB is correctly formated */ + if (length < SUBTLV_RANGE_LABEL_SIZE + || length > SUBTLV_RANGE_INDEX_SIZE) { + stream_forward_getp(s, length); + continue; + } /* RFC 8667 section #3.3: Only one SRLB is authorized */ if (rcap->srlb.range_size != 0) { stream_forward_getp(s, length); @@ -2824,8 +2840,8 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, rcap->srlb.range_size = stream_get3(s); /* Skip Type and get Length of SID Label */ stream_getc(s); - sid_len = stream_getc(s); - if (sid_len == ISIS_SUBTLV_SID_LABEL_SIZE) + size = stream_getc(s); + if (size == ISIS_SUBTLV_SID_LABEL_SIZE) rcap->srlb.lower_bound = stream_get3(s); else rcap->srlb.lower_bound = stream_getl(s); @@ -2839,13 +2855,25 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, rcap->srlb.lower_bound = 0; rcap->srlb.range_size = 0; } + /* Only one range is supported. Skip subsequent one */ + size = length - (size + SUBTLV_SR_BLOCK_SIZE); + if (size > 0) + stream_forward_getp(s, length); break; case ISIS_SUBTLV_NODE_MSD: + /* Check that MSD is correctly formated */ + if (length < MSD_TLV_SIZE) { + stream_forward_getp(s, length); + continue; + } msd_type = stream_getc(s); rcap->msd = stream_getc(s); /* Only BMI-MSD type has been defined in RFC 8491 */ if (msd_type != MSD_TYPE_BASE_MPLS_IMPOSITION) rcap->msd = 0; + /* Only one MSD is standardized. Skip others */ + if (length > MSD_TLV_SIZE) + stream_forward_getp(s, length - MSD_TLV_SIZE); break; default: stream_forward_getp(s, length); diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index 0cf49b526f..1c0d97f2c3 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -140,6 +140,9 @@ struct isis_threeway_adj { #define ISIS_SUBTLV_SRGB_FLAG_V 0x40 #define IS_SR_IPV4(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_I) #define IS_SR_IPV6(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_V) +#define SUBTLV_SR_BLOCK_SIZE 6 +#define SUBTLV_RANGE_INDEX_SIZE 10 +#define SUBTLV_RANGE_LABEL_SIZE 9 /* Structure aggregating SR Global (SRGB) or Local (SRLB) Block info */ struct isis_sr_block { @@ -209,6 +212,9 @@ struct isis_lan_adj_sid { #define SR_ALGORITHM_STRICT_SPF 1 #define SR_ALGORITHM_UNSET 255 +#define MSD_TYPE_BASE_MPLS_IMPOSITION 0x01 +#define MSD_TLV_SIZE 2 + struct isis_router_cap { struct in_addr router_id; uint8_t flags; @@ -218,7 +224,6 @@ struct isis_router_cap { struct isis_sr_block srlb; uint8_t algo[SR_ALGORITHM_COUNT]; /* RFC 8491 */ -#define MSD_TYPE_BASE_MPLS_IMPOSITION 0x01 uint8_t msd; }; -- 2.39.5