Skip to content

Commit 338ec9c

Browse files
[AutoPR- Security] Patch frr for CVE-2026-28532 [MEDIUM] (microsoft#16989)
1 parent 92ce417 commit 338ec9c

2 files changed

Lines changed: 315 additions & 1 deletion

File tree

SPECS/frr/CVE-2026-28532.patch

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
From 263944816e5ea06c9c5dcc35002b819197fbfa60 Mon Sep 17 00:00:00 2001
2+
From: Jafar Al-Gharaibeh <jafar@atcorp.com>
3+
Date: Wed, 4 Mar 2026 12:38:46 -0600
4+
Subject: [PATCH] ospfd: harden TE/SR TLV iteration against malformed lengths
5+
6+
Use 32-bit counters and per-iteration TLV size bounds checks
7+
in OSPF TE/SR TLV parsers so malformed opaque LSAs cannot wrap
8+
loop accounting and advance pointers beyond the LSA buffer.
9+
10+
- Change loop accumulators from 16-bit to 32-bit (uint32_t) to
11+
prevent wraparound
12+
- Rework TLV iteration so pointer advancement is controlled in-loop
13+
- Add per-iteration guard before advancing:
14+
- `tlv_size <= (len - sum)` (or `length - sum`)
15+
- On malformed size, parser now logs and exits/breaks the loop
16+
safely instead of stepping past buffer limits
17+
18+
Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
19+
(cherry picked from commit d3e8aedb87671f38db59b0df908e25e1d4af027d)
20+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
21+
Upstream-reference: https://github.com/FRRouting/frr/commit/c06b61a8586df163fc565667d7bff8e05e0df99d.patch
22+
---
23+
ospfd/ospf_sr.c | 50 ++++++++++++++++++++++++++++++--------
24+
ospfd/ospf_te.c | 64 +++++++++++++++++++++++++++++++++++++++----------
25+
2 files changed, 91 insertions(+), 23 deletions(-)
26+
27+
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
28+
index 078971e..5a9e2c7 100644
29+
--- a/ospfd/ospf_sr.c
30+
+++ b/ospfd/ospf_sr.c
31+
@@ -985,7 +985,8 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
32+
struct ext_subtlv_rmt_itf_addr *rmt_itf;
33+
34+
struct tlv_header *sub_tlvh;
35+
- uint16_t length = 0, sum = 0, i = 0;
36+
+ uint32_t length = 0, sum = 0;
37+
+ uint16_t i = 0;
38+
39+
/* Check TLV size */
40+
if ((ntohs(tlvh->length) > size)
41+
@@ -1000,7 +1001,15 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
42+
length = ntohs(tlvh->length) - EXT_TLV_LINK_SIZE;
43+
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
44+
+ EXT_TLV_LINK_SIZE);
45+
- for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
46+
+ for (; sum < length && sub_tlvh;) {
47+
+ uint32_t tlv_size = TLV_SIZE(sub_tlvh);
48+
+
49+
+ if (tlv_size > length - sum) {
50+
+ zlog_warn("Malformed Extended Link sub-TLV size %u (remaining %u)",
51+
+ tlv_size, length - sum);
52+
+ break;
53+
+ }
54+
+
55+
switch (ntohs(sub_tlvh->type)) {
56+
case EXT_SUBTLV_ADJ_SID:
57+
adj_sid = (struct ext_subtlv_adj_sid *)sub_tlvh;
58+
@@ -1041,7 +1050,9 @@ static struct sr_link *get_ext_link_sid(struct tlv_header *tlvh, size_t size)
59+
default:
60+
break;
61+
}
62+
- sum += TLV_SIZE(sub_tlvh);
63+
+ sum += tlv_size;
64+
+ if (sum < length)
65+
+ sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
66+
}
67+
68+
IPV4_ADDR_COPY(&srl->itf_addr, &link->link_data);
69+
@@ -1062,7 +1073,7 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
70+
struct ext_subtlv_prefix_sid *psid;
71+
72+
struct tlv_header *sub_tlvh;
73+
- uint16_t length = 0, sum = 0;
74+
+ uint32_t length = 0, sum = 0;
75+
76+
/* Check TLV size */
77+
if ((ntohs(tlvh->length) > size)
78+
@@ -1077,7 +1088,15 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
79+
length = ntohs(tlvh->length) - EXT_TLV_PREFIX_SIZE;
80+
sub_tlvh = (struct tlv_header *)((char *)(tlvh) + TLV_HDR_SIZE
81+
+ EXT_TLV_PREFIX_SIZE);
82+
- for (; sum < length && sub_tlvh; sub_tlvh = TLV_HDR_NEXT(sub_tlvh)) {
83+
+ for (; sum < length && sub_tlvh;) {
84+
+ uint32_t tlv_size = TLV_SIZE(sub_tlvh);
85+
+
86+
+ if (tlv_size > length - sum) {
87+
+ zlog_warn("Malformed Extended Prefix sub-TLV size %u (remaining %u)",
88+
+ tlv_size, length - sum);
89+
+ break;
90+
+ }
91+
+
92+
switch (ntohs(sub_tlvh->type)) {
93+
case EXT_SUBTLV_PREFIX_SID:
94+
psid = (struct ext_subtlv_prefix_sid *)sub_tlvh;
95+
@@ -1102,7 +1121,9 @@ static struct sr_prefix *get_ext_prefix_sid(struct tlv_header *tlvh,
96+
default:
97+
break;
98+
}
99+
- sum += TLV_SIZE(sub_tlvh);
100+
+ sum += tlv_size;
101+
+ if (sum < length)
102+
+ sub_tlvh = TLV_HDR_NEXT(sub_tlvh);
103+
}
104+
105+
osr_debug(" |- Found SID %u for prefix %pFX", srp->sid,
106+
@@ -1370,7 +1391,7 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
107+
struct ri_sr_tlv_sid_label_range *ri_srlb = NULL;
108+
struct ri_sr_tlv_sr_algorithm *algo = NULL;
109+
struct sr_block srgb;
110+
- uint16_t length = 0, sum = 0;
111+
+ uint32_t length = 0, sum = 0;
112+
uint8_t msd = 0;
113+
114+
osr_debug("SR (%s): Process Router Information LSA 4.0.0.%u from %pI4",
115+
@@ -1398,8 +1419,15 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
116+
srgb.range_size = 0;
117+
srgb.lower_bound = 0;
118+
119+
- for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);
120+
- tlvh = TLV_HDR_NEXT(tlvh)) {
121+
+ for (tlvh = TLV_HDR_TOP(lsah); (sum < length) && (tlvh != NULL);) {
122+
+ uint32_t tlv_size = TLV_SIZE(tlvh);
123+
+
124+
+ if (tlv_size > length - sum) {
125+
+ zlog_warn("Malformed RI TLV size %u (remaining %u)", tlv_size,
126+
+ length - sum);
127+
+ break;
128+
+ }
129+
+
130+
switch (ntohs(tlvh->type)) {
131+
case RI_SR_TLV_SR_ALGORITHM:
132+
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
133+
@@ -1416,7 +1444,9 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
134+
default:
135+
break;
136+
}
137+
- sum += TLV_SIZE(tlvh);
138+
+ sum += tlv_size;
139+
+ if (sum < length)
140+
+ tlvh = TLV_HDR_NEXT(tlvh);
141+
}
142+
143+
/* Check if Segment Routing Capabilities has been found */
144+
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
145+
index 6fdf98f..6b0355a 100644
146+
--- a/ospfd/ospf_te.c
147+
+++ b/ospfd/ospf_te.c
148+
@@ -2122,7 +2122,7 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
149+
struct ls_attributes *old, attr = {};
150+
struct tlv_header *tlvh;
151+
void *value;
152+
- uint16_t len, sum;
153+
+ uint32_t len, sum;
154+
uint8_t lsa_id;
155+
156+
/* Initialize Attribute */
157+
@@ -2152,11 +2152,19 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
158+
159+
sum = sizeof(struct tlv_header);
160+
/* Browse sub-TLV and fulfill Link State Attributes */
161+
- for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
162+
+ tlvh = TLV_DATA(tlvh);
163+
+ while (sum < len) {
164+
+ uint32_t tlv_size = TLV_SIZE(tlvh);
165+
uint32_t val32, tab32[2];
166+
float valf, tabf[8];
167+
struct in_addr addr;
168+
169+
+ if (tlv_size > len - sum) {
170+
+ zlog_warn("Malformed TE sub-TLV size %u (remaining %u)", tlv_size,
171+
+ len - sum);
172+
+ break;
173+
+ }
174+
+
175+
value = TLV_DATA(tlvh);
176+
switch (ntohs(tlvh->type)) {
177+
case TE_LINK_SUBTLV_LCLIF_IPADDR:
178+
@@ -2251,7 +2259,9 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
179+
default:
180+
break;
181+
}
182+
- sum += TLV_SIZE(tlvh);
183+
+ sum += tlv_size;
184+
+ if (sum < len)
185+
+ tlvh = TLV_HDR_NEXT(tlvh);
186+
}
187+
188+
/* Get corresponding Edge from Link State Data Base */
189+
@@ -2351,7 +2361,7 @@ static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
190+
struct tlv_header *tlvh;
191+
struct in_addr addr;
192+
struct ls_edge_key key = {.family = AF_UNSPEC};
193+
- uint16_t len, sum;
194+
+ uint32_t len, sum;
195+
uint8_t lsa_id;
196+
197+
/* Initialize TLV browsing */
198+
@@ -2363,14 +2373,25 @@ static int ospf_te_delete_te(struct ls_ted *ted, struct ospf_lsa *lsa)
199+
sum = sizeof(struct tlv_header);
200+
201+
/* Browse sub-TLV to find Link ID */
202+
- for (tlvh = TLV_DATA(tlvh); sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
203+
+ tlvh = TLV_DATA(tlvh);
204+
+ while (sum < len) {
205+
+ uint32_t tlv_size = TLV_SIZE(tlvh);
206+
+
207+
+ if (tlv_size > len - sum) {
208+
+ zlog_warn("Malformed TE sub-TLV size %u (remaining %u)", tlv_size,
209+
+ len - sum);
210+
+ break;
211+
+ }
212+
+
213+
if (ntohs(tlvh->type) == TE_LINK_SUBTLV_LCLIF_IPADDR) {
214+
memcpy(&addr, TLV_DATA(tlvh), TE_LINK_SUBTLV_DEF_SIZE);
215+
key.family = AF_INET;
216+
IPV4_ADDR_COPY(&key.k.addr, &addr);
217+
break;
218+
}
219+
- sum += TLV_SIZE(tlvh);
220+
+ sum += tlv_size;
221+
+ if (sum < len)
222+
+ tlvh = TLV_HDR_NEXT(tlvh);
223+
}
224+
if (key.family == AF_UNSPEC)
225+
return 0;
226+
@@ -2445,7 +2466,7 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
227+
struct ls_node *node;
228+
struct lsa_header *lsah = lsa->data;
229+
struct tlv_header *tlvh;
230+
- uint16_t len = 0, sum = 0;
231+
+ uint32_t len = 0, sum = 0;
232+
233+
/* Get vertex / Node from LSA Advertised Router ID */
234+
vertex = get_vertex(ted, lsa);
235+
@@ -2456,13 +2477,18 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
236+
237+
/* Initialize TLV browsing */
238+
len = lsa->size - OSPF_LSA_HEADER_SIZE;
239+
- for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;
240+
- tlvh = TLV_HDR_NEXT(tlvh)) {
241+
+ for (tlvh = TLV_HDR_TOP(lsah); sum < len && tlvh;) {
242+
+ uint32_t tlv_size = TLV_SIZE(tlvh);
243+
struct ri_sr_tlv_sr_algorithm *algo;
244+
struct ri_sr_tlv_sid_label_range *range;
245+
struct ri_sr_tlv_node_msd *msd;
246+
uint32_t size, lower;
247+
248+
+ if (tlv_size > len - sum) {
249+
+ zlog_warn("Malformed RI TLV size %u (remaining %u)", tlv_size, len - sum);
250+
+ break;
251+
+ }
252+
+
253+
switch (ntohs(tlvh->type)) {
254+
case RI_SR_TLV_SR_ALGORITHM:
255+
if (TLV_BODY_SIZE(tlvh) < 1 ||
256+
@@ -2547,7 +2573,9 @@ static int ospf_te_parse_ri(struct ls_ted *ted, struct ospf_lsa *lsa)
257+
default:
258+
break;
259+
}
260+
- sum += TLV_SIZE(tlvh);
261+
+ sum += tlv_size;
262+
+ if (sum < len)
263+
+ tlvh = TLV_HDR_NEXT(tlvh);
264+
}
265+
266+
/* Vertex has been created or updated: export it */
267+
@@ -2759,7 +2787,8 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
268+
struct ext_tlv_link *ext;
269+
struct ls_edge *edge;
270+
struct ls_attributes *atr;
271+
- uint16_t len = 0, sum = 0, i;
272+
+ uint32_t len = 0, sum = 0;
273+
+ uint16_t i;
274+
uint32_t label;
275+
276+
/* Get corresponding Edge from Link State Data Base */
277+
@@ -2793,11 +2822,18 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
278+
len -= EXT_TLV_LINK_SIZE;
279+
tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
280+
+ EXT_TLV_LINK_SIZE);
281+
- for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
282+
+ for (; sum < len;) {
283+
+ uint32_t tlv_size = TLV_SIZE(tlvh);
284+
struct ext_subtlv_adj_sid *adj;
285+
struct ext_subtlv_lan_adj_sid *ladj;
286+
struct ext_subtlv_rmt_itf_addr *rmt;
287+
288+
+ if (tlv_size > len - sum) {
289+
+ zlog_warn("Malformed Extended Link sub-TLV size %u (remaining %u)",
290+
+ tlv_size, len - sum);
291+
+ break;
292+
+ }
293+
+
294+
switch (ntohs(tlvh->type)) {
295+
case EXT_SUBTLV_ADJ_SID:
296+
if (TLV_BODY_SIZE(tlvh) != EXT_SUBTLV_ADJ_SID_SIZE)
297+
@@ -2876,7 +2912,9 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
298+
default:
299+
break;
300+
}
301+
- sum += TLV_SIZE(tlvh);
302+
+ sum += tlv_size;
303+
+ if (sum < len)
304+
+ tlvh = TLV_HDR_NEXT(tlvh);
305+
}
306+
307+
/* Export Link State Edge if needed */
308+
--
309+
2.45.4
310+

SPECS/frr/frr.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Summary: Routing daemon
44
Name: frr
55
Version: 10.5.0
6-
Release: 2%{?dist}
6+
Release: 3%{?dist}
77
License: GPL-2.0-or-later
88
Vendor: Microsoft Corporation
99
Distribution: Azure Linux
@@ -21,6 +21,7 @@ Patch5: 0001-Fix-frr-c90-complaint-error.patch
2121
# CVE-2025-61103, CVE-2025-61104, CVE-2025-61105, CVE-2025-61106 and CVE-2025-61107.
2222
Patch6: CVE-2025-61099.patch
2323
Patch7: CVE-2026-5107.patch
24+
Patch8: CVE-2026-28532.patch
2425
BuildRequires: autoconf
2526
BuildRequires: automake
2627
BuildRequires: bison
@@ -200,6 +201,9 @@ rm tests/lib/*grpc*
200201
%{_sysusersdir}/%{name}.conf
201202

202203
%changelog
204+
* Fri May 01 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 10.5.0-3
205+
- Patch for CVE-2026-28532
206+
203207
* Tue Mar 31 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 10.5.0-2
204208
- Patch for CVE-2026-5107
205209

0 commit comments

Comments
 (0)