Skip to content

Commit 31da0bd

Browse files
authored
Merge pull request FRRouting#20831 from FRRouting/mergify/bp/stable/10.0/pr-20814
bgpd: improve flowspec NLRI validation (backport FRRouting#20814)
2 parents a4223e8 + 16c398f commit 31da0bd

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

bgpd/bgp_flowspec_util.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
171171
int psize;
172172
uint8_t prefix_offset = 0;
173173

174+
/* Need at least 1 byte for prefixlen. */
175+
if (max_len < 1) {
176+
*error = -1;
177+
return 0;
178+
}
179+
174180
*error = 0;
175181
memset(&prefix_local, 0, sizeof(prefix_local));
176182
/* read the prefix length */
@@ -179,6 +185,12 @@ int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
179185
offset++;
180186
prefix_local.family = afi2family(afi);
181187
if (prefix_local.family == AF_INET6) {
188+
/* Need one more byte for IPv6 offset. */
189+
if (offset >= max_len) {
190+
*error = -1;
191+
return offset;
192+
}
193+
182194
prefix_offset = nlri_ptr[offset];
183195
if (ipv6_offset)
184196
*ipv6_offset = prefix_offset;
@@ -254,13 +266,32 @@ int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
254266
struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
255267

256268
*error = 0;
269+
270+
/* do/while executes at least once, so guard first deref */
271+
if (max_len < 1) {
272+
*error = -1;
273+
return 0;
274+
}
275+
257276
do {
258277
if (loop > BGP_PBR_MATCH_VAL_MAX)
259278
*error = -2;
279+
280+
if (offset >= max_len) {
281+
*error = -1;
282+
break;
283+
}
284+
260285
hex2bin(&nlri_ptr[offset], op);
261286
offset++;
262287
len = 2*op[2]+op[3];
263288
value_size = 1 << len;
289+
290+
if (offset > max_len || (uint32_t)value_size > (max_len - offset)) {
291+
*error = -1;
292+
break;
293+
}
294+
264295
value = hexstr2num(&nlri_ptr[offset], value_size);
265296
/* can not be < and > at the same time */
266297
if (op[5] == 1 && op[6] == 1)
@@ -358,18 +389,32 @@ int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
358389
int len_written;
359390

360391
*error = 0;
392+
393+
/* do/while executes at least once, so guard first deref */
394+
if (max_len < 1) {
395+
*error = -1;
396+
return 0;
397+
}
398+
361399
do {
362400
if (loop > BGP_PBR_MATCH_VAL_MAX) {
363401
*error = -2;
364402
return offset;
365403
}
404+
366405
hex2bin(&nlri_ptr[offset], op);
367406
/* if first element, AND bit can not be set */
368407
if (op[1] == 1 && loop == 0)
369408
*error = -1;
370409
offset++;
371410
len = 2 * op[2] + op[3];
372411
value_size = 1 << len;
412+
413+
if (offset > max_len || (uint32_t)value_size > (max_len - offset)) {
414+
*error = -1;
415+
break;
416+
}
417+
373418
value = hexstr2num(&nlri_ptr[offset], value_size);
374419
switch (type) {
375420
case BGP_FLOWSPEC_RETURN_STRING:

0 commit comments

Comments
 (0)