VYPR
Medium severity6.5NVD Advisory· Published Apr 30, 2026· Updated May 1, 2026

CVE-2026-28532

CVE-2026-28532

Description

FRRouting before 10.5.3 contains an integer overflow vulnerability in seven OSPF Traffic Engineering and Segment Routing TLV parser functions where a uint16_t accumulator variable truncates uint32_t values returned by the TLV_SIZE() macro, causing the loop termination condition to fail while pointer advancement continues unchecked. Attackers with an established OSPF adjacency can send a crafted LS Update packet with a malicious Type 10 or Type 11 Opaque LSA to trigger out-of-bounds memory reads and crash all affected routers in the OSPF area or autonomous system.

Affected products

1

Patches

1
f098decf0298

Merge pull request #21002 from Jafaral/ospf-fix

https://github.com/FRRouting/frrMark StappMar 5, 2026via nvd-ref
2 files changed · +91 23
  • ospfd/ospf_sr.c+40 10 modified
    @@ -989,7 +989,8 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
     	struct ext_subtlv_rmt_itf_addr *rmt_itf;
     
     	struct tlv_header *sub_tlvh;
    -	uint16_t length = 0, sum = 0, i = 0;
    +	uint32_t length = 0, sum = 0;
    +	uint16_t i = 0;
     
     	/* Check TLV size */
     	if ((ntohs(tlvh->length) > size)
    @@ -1004,7 +1005,15 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
     	length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
     	sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
     					 + EXT_TLV_LINK_SIZE);
    -	for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
    +	for (; sum < length && sub_tlvh;) {
    +		uint32_t tlv_size = TLV_SIZE(sub_tlvh);
    +
    +		if (tlv_size > length - sum) {
    +			zlog_warn("Malformed Extended Link sub-TLV size %u (remaining %u)",
    +				  tlv_size, length - sum);
    +			break;
    +		}
    +
     		switch (ntohs(sub_tlvh->type)) {
     		case EXT_SUBTLV_ADJ_SID:
     			adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
    @@ -1045,7 +1054,9 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(sub_tlvh);
    +		sum += tlv_size;
    +		if (sum < length)
    +			sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
     	}
     
     	IPV4_ADDR_COPY(&srl->itf_addr, &link->link_data);
    @@ -1066,7 +1077,7 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
     	struct ext_subtlv_prefix_sid *psid;
     
     	struct tlv_header *sub_tlvh;
    -	uint16_t length = 0, sum = 0;
    +	uint32_t length = 0, sum = 0;
     
     	/* Check TLV size */
     	if ((ntohs(tlvh->length) > size)
    @@ -1081,7 +1092,15 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
     	length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
     	sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
     					 + EXT_TLV_PREFIX_SIZE);
    -	for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
    +	for (; sum < length && sub_tlvh;) {
    +		uint32_t tlv_size = TLV_SIZE(sub_tlvh);
    +
    +		if (tlv_size > length - sum) {
    +			zlog_warn("Malformed Extended Prefix sub-TLV size %u (remaining %u)",
    +				  tlv_size, length - sum);
    +			break;
    +		}
    +
     		switch (ntohs(sub_tlvh->type)) {
     		case EXT_SUBTLV_PREFIX_SID:
     			psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
    @@ -1106,7 +1125,9 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(sub_tlvh);
    +		sum += tlv_size;
    +		if (sum < length)
    +			sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
     	}
     
     	osr_debug("  |-  Found SID %u for prefix %pFX", srp->sid,
    @@ -1374,7 +1395,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
     	struct ri_sr_tlv_sid_label_range *ri_srlb = NULL;
     	struct ri_sr_tlv_sr_algorithm *algo = NULL;
     	struct sr_block srgb;
    -	uint16_t length = 0, sum = 0;
    +	uint32_t length = 0, sum = 0;
     	uint8_t msd = 0;
     
     	osr_debug("SR (%s): Process Router Information LSA 4.0.0.%u from %pI4",
    @@ -1402,8 +1423,15 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
     	srgb.range_size = 0;
     	srgb.lower_bound = 0;
     
    -	for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
    -	     tlvh = TLV_HDR_NEXT(tlvh)) {
    +	for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);) {
    +		uint32_t tlv_size = TLV_SIZE(tlvh);
    +
    +		if (tlv_size > length - sum) {
    +			zlog_warn("Malformed RI TLV size %u (remaining %u)", tlv_size,
    +				  length - sum);
    +			break;
    +		}
    +
     		switch (ntohs(tlvh->type)) {
     		case RI_SR_TLV_SR_ALGORITHM:
     			algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
    @@ -1420,7 +1448,9 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(tlvh);
    +		sum += tlv_size;
    +		if (sum < length)
    +			tlvh = TLV_HDR_NEXT(tlvh);
     	}
     
     	/* Check if Segment Routing Capabilities has been found */
    
  • ospfd/ospf_te.c+51 13 modified
    @@ -2119,7 +2119,7 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
     	struct ls_attributes *old, attr = {};
     	struct tlv_header *tlvh;
     	void *value;
    -	uint16_t len, sum;
    +	uint32_t len, sum;
     	uint8_t lsa_id;
     
     	/* Initialize Attribute */
    @@ -2149,11 +2149,19 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
     
     	sum = sizeof(struct tlv_header);
     	/* Browse sub-TLV and fulfill Link State Attributes */
    -	for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
    +	tlvh = TLV_DATA(tlvh);
    +	while (sum < len) {
    +		uint32_t tlv_size = TLV_SIZE(tlvh);
     		uint32_t val32, tab32[2];
     		float valf, tabf[8];
     		struct in_addr addr;
     
    +		if (tlv_size > len - sum) {
    +			zlog_warn("Malformed TE sub-TLV size %u (remaining %u)", tlv_size,
    +				  len - sum);
    +			break;
    +		}
    +
     		value = TLV_DATA(tlvh);
     		switch (ntohs(tlvh->type)) {
     		case TE_LINK_SUBTLV_LCLIF_IPADDR:
    @@ -2248,7 +2256,9 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(tlvh);
    +		sum += tlv_size;
    +		if (sum < len)
    +			tlvh = TLV_HDR_NEXT(tlvh);
     	}
     
     	/* Get corresponding Edge from Link State Data Base */
    @@ -2348,7 +2358,7 @@ static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
     	struct tlv_header *tlvh;
     	struct in_addr addr;
     	struct ls_edge_key key = {.family = AF_UNSPEC};
    -	uint16_t len, sum;
    +	uint32_t len, sum;
     	uint8_t lsa_id;
     
     	/* Initialize TLV browsing */
    @@ -2360,14 +2370,25 @@ static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
     	sum = sizeof(struct tlv_header);
     
     	/* Browse sub-TLV to find Link ID */
    -	for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
    +	tlvh = TLV_DATA(tlvh);
    +	while (sum < len) {
    +		uint32_t tlv_size = TLV_SIZE(tlvh);
    +
    +		if (tlv_size > len - sum) {
    +			zlog_warn("Malformed TE sub-TLV size %u (remaining %u)", tlv_size,
    +				  len - sum);
    +			break;
    +		}
    +
     		if (ntohs(tlvh->type) == TE_LINK_SUBTLV_LCLIF_IPADDR) {
     			memcpy(&addr, TLV_DATA(tlvh), TE_LINK_SUBTLV_DEF_SIZE);
     			key.family = AF_INET;
     			IPV4_ADDR_COPY(&key.k.addr, &addr);
     			break;
     		}
    -		sum += TLV_SIZE(tlvh);
    +		sum += tlv_size;
    +		if (sum < len)
    +			tlvh = TLV_HDR_NEXT(tlvh);
     	}
     	if (key.family == AF_UNSPEC)
     		return 0;
    @@ -2442,7 +2463,7 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
     	struct ls_node *node;
     	struct lsa_header *lsah = lsa->data;
     	struct tlv_header *tlvh;
    -	uint16_t len = 0, sum = 0;
    +	uint32_t len = 0, sum = 0;
     
     	/* Get vertex / Node from LSA Advertised Router ID */
     	vertex = get_vertex(ted, lsa);
    @@ -2453,13 +2474,18 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
     
     	/* Initialize TLV browsing */
     	len = lsa->size - OSPF_LSA_HEADER_SIZE;
    -	for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
    -	     tlvh = TLV_HDR_NEXT(tlvh)) {
    +	for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;) {
    +		uint32_t tlv_size = TLV_SIZE(tlvh);
     		struct ri_sr_tlv_sr_algorithm *algo;
     		struct ri_sr_tlv_sid_label_range *range;
     		struct ri_sr_tlv_node_msd *msd;
     		uint32_t size, lower;
     
    +		if (tlv_size > len - sum) {
    +			zlog_warn("Malformed RI TLV size %u (remaining %u)", tlv_size, len - sum);
    +			break;
    +		}
    +
     		switch (ntohs(tlvh->type)) {
     		case RI_SR_TLV_SR_ALGORITHM:
     			if (TLV_BODY_SIZE(tlvh) < 1 ||
    @@ -2544,7 +2570,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(tlvh);
    +		sum += tlv_size;
    +		if (sum < len)
    +			tlvh = TLV_HDR_NEXT(tlvh);
     	}
     
     	/* Vertex has been created or updated: export it */
    @@ -2756,7 +2784,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
     	struct ext_tlv_link *ext;
     	struct ls_edge *edge;
     	struct ls_attributes *atr;
    -	uint16_t len = 0, sum = 0, i;
    +	uint32_t len = 0, sum = 0;
    +	uint16_t i;
     	uint32_t label;
     
     	/* Get corresponding Edge from Link State Data Base */
    @@ -2790,11 +2819,18 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
     	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)) {
    +	for (; sum < len;) {
    +		uint32_t tlv_size = TLV_SIZE(tlvh);
     		struct ext_subtlv_adj_sid *adj;
     		struct ext_subtlv_lan_adj_sid *ladj;
     		struct ext_subtlv_rmt_itf_addr *rmt;
     
    +		if (tlv_size > len - sum) {
    +			zlog_warn("Malformed Extended Link sub-TLV size %u (remaining %u)",
    +				  tlv_size, len - sum);
    +			break;
    +		}
    +
     		switch (ntohs(tlvh->type)) {
     		case EXT_SUBTLV_ADJ_SID:
     			if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_ADJ_SID_SIZE)
    @@ -2873,7 +2909,9 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
     		default:
     			break;
     		}
    -		sum += TLV_SIZE(tlvh);
    +		sum += tlv_size;
    +		if (sum < len)
    +			tlvh = TLV_HDR_NEXT(tlvh);
     	}
     
     	/* Export Link State Edge if needed */
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.