diff --git a/0021-ospfd-Solved-crash-in-RI-parsing-with-OSPF-TE.patch b/0021-ospfd-Solved-crash-in-RI-parsing-with-OSPF-TE.patch new file mode 100644 index 0000000..09ff0a3 --- /dev/null +++ b/0021-ospfd-Solved-crash-in-RI-parsing-with-OSPF-TE.patch @@ -0,0 +1,67 @@ +From 298704f1e73221172432e2a4afd79086ffcd4cca Mon Sep 17 00:00:00 2001 +From: Olivier Dugeon +Date: Wed, 3 Apr 2024 16:28:23 +0200 +Upstream: yes +References: CVE-2024-31950,bsc#1222526,gh#FRRouting/frr#16088 +Subject: [PATCH 1/3] ospfd: Solved crash in RI parsing with OSPF TE + +Iggy Frankovic discovered another ospfd crash when performing fuzzing of OSPF +LSA packets. The crash occurs in ospf_te_parse_ri() function when attemping to +read Segment Routing subTLVs. The original code doesn't check if the size of +the SR subTLVs have the correct length. In presence of erronous LSA, this will +cause a buffer overflow and ospfd crash. + +This patch introduces new verification of the subTLVs size for Router +Information TLV. + +Co-authored-by: Iggy Frankovic +Signed-off-by: Olivier Dugeon +(cherry picked from commit f69d1313b19047d3d83fc2b36a518355b861dfc4) +--- + ospfd/ospf_te.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c +index 45eb205759..885b915585 100644 +--- a/ospfd/ospf_te.c ++++ b/ospfd/ospf_te.c +@@ -2483,6 +2483,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++) { +@@ -2507,6 +2510,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)); +@@ -2524,6 +2529,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)); +@@ -2541,6 +2548,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)) +-- +2.35.3 + diff --git a/0022-ospfd-Correct-Opaque-LSA-Extended-parser.patch b/0022-ospfd-Correct-Opaque-LSA-Extended-parser.patch new file mode 100644 index 0000000..2e2a40a --- /dev/null +++ b/0022-ospfd-Correct-Opaque-LSA-Extended-parser.patch @@ -0,0 +1,109 @@ +From 4e70b09f24b72fbb27ff5eda63393bfd2a72ef37 Mon Sep 17 00:00:00 2001 +From: Olivier Dugeon +Date: Fri, 5 Apr 2024 12:57:11 +0200 +Upstream: yes +References: CVE-2024-31951,bsc#1222528,gh#FRRouting/frr#16088 +Subject: [PATCH 2/3] ospfd: Correct Opaque LSA Extended parser + +Iggy Frankovic discovered another ospfd crash when performing fuzzing of OSPF +LSA packets. The crash occurs in ospf_te_parse_ext_link() function when +attemping to read Segment Routing Adjacency SID subTLVs. The original code +doesn't check if the size of the Extended Link TLVs and subTLVs have the correct +length. In presence of erronous LSA, this will cause a buffer overflow and ospfd +crashes. + +This patch introduces new verification of the subTLVs size for Extended Link +TLVs and subTLVs. Similar check has been also introduced for the Extended +Prefix TLV. + +Co-authored-by: Iggy Frankovic +Signed-off-by: Olivier Dugeon +(cherry picked from commit 5557a289acdaeec8cc63ffc97b5c2abf6dee7b3a) +--- + ospfd/ospf_te.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c +index 885b915585..23a1b181ec 100644 +--- a/ospfd/ospf_te.c ++++ b/ospfd/ospf_te.c +@@ -2647,6 +2647,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); +@@ -2668,6 +2669,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 +@@ -2778,8 +2791,20 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa) + 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)) { +@@ -2789,6 +2814,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) +@@ -2815,6 +2842,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) +@@ -2844,6 +2873,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, +-- +2.35.3 + diff --git a/0023-ospfd-protect-call-to-get_edge-in-ospf_te.c.patch b/0023-ospfd-protect-call-to-get_edge-in-ospf_te.c.patch new file mode 100644 index 0000000..e6073bf --- /dev/null +++ b/0023-ospfd-protect-call-to-get_edge-in-ospf_te.c.patch @@ -0,0 +1,82 @@ +From cef38442420aeac8e163f8aa55f1b985908f993c Mon Sep 17 00:00:00 2001 +From: Olivier Dugeon +Date: Tue, 16 Apr 2024 16:42:06 +0200 +Upstream: yes +References: CVE-2024-34088,bsc#1223786,gh#FRRouting/frr#16088 +Subject: [PATCH 3/3] ospfd: protect call to get_edge() in ospf_te.c + +During fuzzing, Iggy Frankovic discovered that get_edge() function in ospf_te.c +could return null pointer, in particular when the link_id or advertised router +IP addresses are fuzzed. As the null pointer returned by get_edge() function is +not handlei by calling functions, this could cause ospfd crash. + +This patch introduces new verification of returned pointer by get_edge() +function and stop the processing in case of null pointer. In addition, link ID +and advertiser router ID are validated before calling ls_find_edge_by_key() to +avoid the creation of a new edge with an invalid key. + +CVE-2024-34088 + +Co-authored-by: Iggy Frankovic +Signed-off-by: Olivier Dugeon +(cherry picked from commit 8c177d69e32b91b45bda5fc5da6511fa03dc11ca) +--- + ospfd/ospf_te.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c +index 23a1b181ec..d1f114e30a 100644 +--- a/ospfd/ospf_te.c ++++ b/ospfd/ospf_te.c +@@ -1686,6 +1686,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 = ((uint64_t)ntohl(link_id.s_addr)) & 0xffffffff; + edge = ls_find_edge_by_key(ted, key); +@@ -1758,6 +1763,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 */ +@@ -2276,11 +2285,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", +@@ -2786,6 +2795,10 @@ 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", +-- +2.35.3 + diff --git a/frr.changes b/frr.changes index 8ab2300..d421f56 100644 --- a/frr.changes +++ b/frr.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Tue Jun 4 21:27:48 UTC 2024 - Marius Tomaschewski + +- Apply upstream fix solving ospfd denial of service via get_edge() + function returning a NULL pointer (CVE-2024-34088,bsc#1223786, + gh#FRRouting/frr#16088). + [+ 0023-ospfd-protect-call-to-get_edge-in-ospf_te.c.patch] +- Apply upstream fix solving ospfd buffer overflow and daemon crash + in ospf_te_parse_ext_link for OSPF LSA packets during an attempt + to read Segment Routing Adjacency SID subTLVs (CVE-2024-31951, + bsc#1222528,gh#FRRouting/frr#16088). + [+ 0022-ospfd-Correct-Opaque-LSA-Extended-parser.patch] +- Apply upstream fix solving ospfd buffer overflow and daemon crash + in RI parsing with OSPF TE (CVE-2024-31950,bsc#1222526, + gh#FRRouting/frr#16088). + [+ 0021-ospfd-Solved-crash-in-RI-parsing-with-OSPF-TE.patch] + ------------------------------------------------------------------- Wed Apr 24 10:40:57 UTC 2024 - Marius Tomaschewski diff --git a/frr.spec b/frr.spec index 0e867d2..be0610b 100644 --- a/frr.spec +++ b/frr.spec @@ -59,6 +59,9 @@ Patch17: 0017-bgpd-Fix-use-beyond-end-of-stream-of-labeled-unicast.patch Patch18: 0018-bgpd-Flowspec-overflow-issue.patch Patch19: 0019-bgpd-fix-error-handling-when-receiving-BGP-Prefix-SID-attribute.patch Patch20: 0020-ospfd-Solved-crash-in-OSPF-TE-parsing.patch +Patch21: 0021-ospfd-Solved-crash-in-RI-parsing-with-OSPF-TE.patch +Patch22: 0022-ospfd-Correct-Opaque-LSA-Extended-parser.patch +Patch23: 0023-ospfd-protect-call-to-get_edge-in-ospf_te.c.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: bison >= 2.7