diff options
| author | Donald Sharp <donaldsharp72@gmail.com> | 2024-05-25 10:51:17 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-25 10:51:17 -0400 | 
| commit | e1170c6f0c6767edc418364a4b4e010584f5ff93 (patch) | |
| tree | 0fce52e6b8fc5778625c5aa0728bb3fb5d0ddd4c | |
| parent | 80f125d8b7729b830dfa71e53c4c9cff8d7afbcd (diff) | |
| parent | 26ea8574cd3c0c2447be30b47ee908bd3d707c38 (diff) | |
Merge pull request #16084 from FRRouting/mergify/bp/stable/10.0/pr-15674
ospfd: Solved crash in RI parsing with OSPF TE (backport #15674)
| -rw-r--r-- | ospfd/ospf_te.c | 63 | 
1 files changed, 58 insertions, 5 deletions
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 80ebab3ef6..b1563b5bda 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1670,6 +1670,11 @@ static struct ls_edge *get_edge(struct ls_ted *ted, struct ls_node_id adv,  	struct ls_edge *edge;  	struct ls_attributes *attr; +	/* Check that Link ID and Node ID are valid */ +	if (IPV4_NET0(link_id.s_addr) || IPV4_NET0(adv.id.ip.addr.s_addr) || +	    adv.origin != OSPFv2) +		return NULL; +  	/* Search Edge that corresponds to the Link ID */  	key.family = AF_INET;  	IPV4_ADDR_COPY(&key.k.addr, &link_id); @@ -1743,6 +1748,10 @@ static void ospf_te_update_link(struct ls_ted *ted, struct ls_vertex *vertex,  	/* Get Corresponding Edge from Link State Data Base */  	edge = get_edge(ted, vertex->node->adv, link_data); +	if (!edge) { +		ote_debug("  |- Found no edge from Link Data. Abort!"); +		return; +	}  	attr = edge->attributes;  	/* re-attached edge to vertex if needed */ @@ -2246,11 +2255,11 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)  	}  	/* Get corresponding Edge from Link State Data Base */ -	if (IPV4_NET0(attr.standard.local.s_addr) && !attr.standard.local_id) { -		ote_debug("  |- Found no TE Link local address/ID. Abort!"); +	edge = get_edge(ted, attr.adv, attr.standard.local); +	if (!edge) { +		ote_debug("  |- Found no edge from Link local add./ID. Abort!");  		return -1;  	} -	edge = get_edge(ted, attr.adv, attr.standard.local);  	old = edge->attributes;  	ote_debug("  |- Process Traffic Engineering LSA %pI4 for Edge %pI4", @@ -2456,6 +2465,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)  		switch (ntohs(tlvh->type)) {  		case RI_SR_TLV_SR_ALGORITHM: +			if (TLV_BODY_SIZE(tlvh) < 1 || +			    TLV_BODY_SIZE(tlvh) > ALGORITHM_COUNT) +				break;  			algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;  			for (int i = 0; i < ntohs(algo->header.length); i++) { @@ -2480,6 +2492,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)  			break;  		case RI_SR_TLV_SRGB_LABEL_RANGE: +			if (TLV_BODY_SIZE(tlvh) != RI_SR_TLV_LABEL_RANGE_SIZE) +				break;  			range = (struct ri_sr_tlv_sid_label_range *)tlvh;  			size = GET_RANGE_SIZE(ntohl(range->size));  			lower = GET_LABEL(ntohl(range->lower.value)); @@ -2497,6 +2511,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)  			break;  		case RI_SR_TLV_SRLB_LABEL_RANGE: +			if (TLV_BODY_SIZE(tlvh) != RI_SR_TLV_LABEL_RANGE_SIZE) +				break;  			range = (struct ri_sr_tlv_sid_label_range *)tlvh;  			size = GET_RANGE_SIZE(ntohl(range->size));  			lower = GET_LABEL(ntohl(range->lower.value)); @@ -2514,6 +2530,8 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)  			break;  		case RI_SR_TLV_NODE_MSD: +			if (TLV_BODY_SIZE(tlvh) < RI_SR_TLV_NODE_MSD_SIZE) +				break;  			msd = (struct ri_sr_tlv_node_msd *)tlvh;  			if ((CHECK_FLAG(node->flags, LS_NODE_MSD))  			    && (node->msd == msd->value)) @@ -2611,6 +2629,7 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)  	struct ext_tlv_prefix *ext;  	struct ext_subtlv_prefix_sid *pref_sid;  	uint32_t label; +	uint16_t len, size;  	/* Get corresponding Subnet from Link State Data Base */  	ext = (struct ext_tlv_prefix *)TLV_HDR_TOP(lsa->data); @@ -2632,6 +2651,18 @@ static int ospf_te_parse_ext_pref(struct ls_ted *ted, struct ospf_lsa *lsa)  	ote_debug("  |- Process Extended Prefix LSA %pI4 for subnet %pFX",  		  &lsa->data->id, &pref); +	/* +	 * Check Extended Prefix TLV size against LSA size +	 * as only one TLV is allowed per LSA +	 */ +	len = TLV_BODY_SIZE(&ext->header); +	size = lsa->size - (OSPF_LSA_HEADER_SIZE + TLV_HDR_SIZE); +	if (len != size || len <= 0) { +		ote_debug("  |- Wrong TLV size: %u instead of %u", +			  (uint32_t)len, (uint32_t)size); +		return -1; +	} +  	/* Initialize TLV browsing */  	ls_pref = subnet->ls_pref;  	pref_sid = (struct ext_subtlv_prefix_sid *)((char *)(ext) + TLV_HDR_SIZE @@ -2737,13 +2768,29 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)  	lnid.id.ip.area_id = lsa->area->area_id;  	ext = (struct ext_tlv_link *)TLV_HDR_TOP(lsa->data);  	edge = get_edge(ted, lnid, ext->link_data); +	if (!edge) { +		ote_debug("  |- Found no edge from Extended Link Data. Abort!"); +		return -1; +	}  	atr = edge->attributes;  	ote_debug("  |- Process Extended Link LSA %pI4 for edge %pI4",  		  &lsa->data->id, &edge->attributes->standard.local); -	/* Initialize TLV browsing */ -	len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE; +	/* +	 * Check Extended Link TLV size against LSA size +	 * as only one TLV is allowed per LSA +	 */ +	len = TLV_BODY_SIZE(&ext->header); +	i = lsa->size - (OSPF_LSA_HEADER_SIZE + TLV_HDR_SIZE); +	if (len != i || len <= 0) { +		ote_debug("  |- Wrong TLV size: %u instead of %u", +			  (uint32_t)len, (uint32_t)i); +		return -1; +	} + +	/* Initialize subTLVs browsing */ +	len -= EXT_TLV_LINK_SIZE;  	tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE  				     + EXT_TLV_LINK_SIZE);  	for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) { @@ -2753,6 +2800,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)  		switch (ntohs(tlvh->type)) {  		case EXT_SUBTLV_ADJ_SID: +			if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_ADJ_SID_SIZE) +				break;  			adj = (struct ext_subtlv_adj_sid *)tlvh;  			label = CHECK_FLAG(adj->flags,  					   EXT_SUBTLV_LINK_ADJ_SID_VFLG) @@ -2779,6 +2828,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)  			break;  		case EXT_SUBTLV_LAN_ADJ_SID: +			if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_LAN_ADJ_SID_SIZE) +				break;  			ladj = (struct ext_subtlv_lan_adj_sid *)tlvh;  			label = CHECK_FLAG(ladj->flags,  					   EXT_SUBTLV_LINK_ADJ_SID_VFLG) @@ -2808,6 +2859,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)  			break;  		case EXT_SUBTLV_RMT_ITF_ADDR: +			if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_RMT_ITF_ADDR_SIZE) +				break;  			rmt = (struct ext_subtlv_rmt_itf_addr *)tlvh;  			if (CHECK_FLAG(atr->flags, LS_ATTR_NEIGH_ADDR)  			    && IPV4_ADDR_SAME(&atr->standard.remote,  | 
