Merge pull request #10517 from idryzhov/isis_router_cap_tlv_fixes

isisd: fix router capability TLV parsing issues
This commit is contained in:
Russ White 2022-02-08 08:35:45 -05:00 committed by GitHub
commit 107f77b56f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 11 deletions

View File

@ -3007,28 +3007,55 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context,
type = stream_getc(s); type = stream_getc(s);
length = stream_getc(s); length = stream_getc(s);
if (length > STREAM_READABLE(s) || length > subtlv_len - 2) {
sbuf_push(
log, indent,
"WARNING: Router Capability subTLV length too large compared to expected size\n");
stream_forward_getp(s, STREAM_READABLE(s));
return 0;
}
switch (type) { switch (type) {
case ISIS_SUBTLV_SID_LABEL_RANGE: case ISIS_SUBTLV_SID_LABEL_RANGE:
/* Check that SRGB is correctly formated */ /* Check that SRGB is correctly formated */
if (length < SUBTLV_RANGE_LABEL_SIZE if (length < SUBTLV_RANGE_LABEL_SIZE
|| length > SUBTLV_RANGE_INDEX_SIZE) { || length > SUBTLV_RANGE_INDEX_SIZE) {
stream_forward_getp(s, length); stream_forward_getp(s, length);
continue; break;
} }
/* Only one SRGB is supported. Skip subsequent one */ /* Only one SRGB is supported. Skip subsequent one */
if (rcap->srgb.range_size != 0) { if (rcap->srgb.range_size != 0) {
stream_forward_getp(s, length); stream_forward_getp(s, length);
continue; break;
} }
rcap->srgb.flags = stream_getc(s); rcap->srgb.flags = stream_getc(s);
rcap->srgb.range_size = stream_get3(s); rcap->srgb.range_size = stream_get3(s);
/* Skip Type and get Length of SID Label */ /* Skip Type and get Length of SID Label */
stream_getc(s); stream_getc(s);
size = stream_getc(s); size = stream_getc(s);
if (size == ISIS_SUBTLV_SID_LABEL_SIZE)
if (size == ISIS_SUBTLV_SID_LABEL_SIZE
&& length != SUBTLV_RANGE_LABEL_SIZE) {
stream_forward_getp(s, length - 6);
break;
}
if (size == ISIS_SUBTLV_SID_INDEX_SIZE
&& length != SUBTLV_RANGE_INDEX_SIZE) {
stream_forward_getp(s, length - 6);
break;
}
if (size == ISIS_SUBTLV_SID_LABEL_SIZE) {
rcap->srgb.lower_bound = stream_get3(s); rcap->srgb.lower_bound = stream_get3(s);
else } else if (size == ISIS_SUBTLV_SID_INDEX_SIZE) {
rcap->srgb.lower_bound = stream_getl(s); rcap->srgb.lower_bound = stream_getl(s);
} else {
stream_forward_getp(s, length - 6);
break;
}
/* SRGB sanity checks. */ /* SRGB sanity checks. */
if (rcap->srgb.range_size == 0 if (rcap->srgb.range_size == 0
@ -3042,9 +3069,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context,
/* Only one range is supported. Skip subsequent one */ /* Only one range is supported. Skip subsequent one */
size = length - (size + SUBTLV_SR_BLOCK_SIZE); size = length - (size + SUBTLV_SR_BLOCK_SIZE);
if (size > 0) if (size > 0)
stream_forward_getp(s, length); stream_forward_getp(s, size);
break; break;
case ISIS_SUBTLV_ALGORITHM: case ISIS_SUBTLV_ALGORITHM:
if (length == 0)
break;
/* Only 2 algorithms are supported: SPF & Strict SPF */ /* Only 2 algorithms are supported: SPF & Strict SPF */
stream_get(&rcap->algo, s, stream_get(&rcap->algo, s,
length > SR_ALGORITHM_COUNT length > SR_ALGORITHM_COUNT
@ -3059,12 +3089,12 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context,
if (length < SUBTLV_RANGE_LABEL_SIZE if (length < SUBTLV_RANGE_LABEL_SIZE
|| length > SUBTLV_RANGE_INDEX_SIZE) { || length > SUBTLV_RANGE_INDEX_SIZE) {
stream_forward_getp(s, length); stream_forward_getp(s, length);
continue; break;
} }
/* RFC 8667 section #3.3: Only one SRLB is authorized */ /* RFC 8667 section #3.3: Only one SRLB is authorized */
if (rcap->srlb.range_size != 0) { if (rcap->srlb.range_size != 0) {
stream_forward_getp(s, length); stream_forward_getp(s, length);
continue; break;
} }
/* Ignore Flags which are not defined */ /* Ignore Flags which are not defined */
stream_getc(s); stream_getc(s);
@ -3072,10 +3102,27 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context,
/* Skip Type and get Length of SID Label */ /* Skip Type and get Length of SID Label */
stream_getc(s); stream_getc(s);
size = stream_getc(s); size = stream_getc(s);
if (size == ISIS_SUBTLV_SID_LABEL_SIZE)
if (size == ISIS_SUBTLV_SID_LABEL_SIZE
&& length != SUBTLV_RANGE_LABEL_SIZE) {
stream_forward_getp(s, length - 6);
break;
}
if (size == ISIS_SUBTLV_SID_INDEX_SIZE
&& length != SUBTLV_RANGE_INDEX_SIZE) {
stream_forward_getp(s, length - 6);
break;
}
if (size == ISIS_SUBTLV_SID_LABEL_SIZE) {
rcap->srlb.lower_bound = stream_get3(s); rcap->srlb.lower_bound = stream_get3(s);
else } else if (size == ISIS_SUBTLV_SID_INDEX_SIZE) {
rcap->srlb.lower_bound = stream_getl(s); rcap->srlb.lower_bound = stream_getl(s);
} else {
stream_forward_getp(s, length - 6);
break;
}
/* SRLB sanity checks. */ /* SRLB sanity checks. */
if (rcap->srlb.range_size == 0 if (rcap->srlb.range_size == 0
@ -3089,13 +3136,14 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context,
/* Only one range is supported. Skip subsequent one */ /* Only one range is supported. Skip subsequent one */
size = length - (size + SUBTLV_SR_BLOCK_SIZE); size = length - (size + SUBTLV_SR_BLOCK_SIZE);
if (size > 0) if (size > 0)
stream_forward_getp(s, length); stream_forward_getp(s, size);
break; break;
case ISIS_SUBTLV_NODE_MSD: case ISIS_SUBTLV_NODE_MSD:
/* Check that MSD is correctly formated */ /* Check that MSD is correctly formated */
if (length < MSD_TLV_SIZE) { if (length < MSD_TLV_SIZE) {
stream_forward_getp(s, length); stream_forward_getp(s, length);
continue; break;
} }
msd_type = stream_getc(s); msd_type = stream_getc(s);
rcap->msd = stream_getc(s); rcap->msd = stream_getc(s);

View File

@ -447,6 +447,7 @@ enum ext_subtlv_size {
/* RFC 8667 sections #2 & #3 */ /* RFC 8667 sections #2 & #3 */
ISIS_SUBTLV_SID_LABEL_SIZE = 3, ISIS_SUBTLV_SID_LABEL_SIZE = 3,
ISIS_SUBTLV_SID_INDEX_SIZE = 4,
ISIS_SUBTLV_SID_LABEL_RANGE_SIZE = 9, ISIS_SUBTLV_SID_LABEL_RANGE_SIZE = 9,
ISIS_SUBTLV_ALGORITHM_SIZE = 4, ISIS_SUBTLV_ALGORITHM_SIZE = 4,
ISIS_SUBTLV_ADJ_SID_SIZE = 5, ISIS_SUBTLV_ADJ_SID_SIZE = 5,