<div dir="auto">Hi,<div dir="auto"><br></div><div dir="auto">AFAIK, ASPA RFC forbid AS sets and considers such announces invalid:</div><div dir="auto"><br></div><div dir="auto"><a href="https://www.ietf.org/archive/id/draft-ietf-sidrops-aspa-verification-22.html#section-6.2-3.3.1">https://www.ietf.org/archive/id/draft-ietf-sidrops-aspa-verification-22.html#section-6.2-3.3.1</a></div><div dir="auto"><br></div><div dir="auto">> If the AS_PATH has an AS_SET, then the procedure halts with the outcome "Invalid".</div><div dir="auto"><br></div><div dir="auto">Regards,</div><div dir="auto">Alexander</div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sun, Aug 31, 2025, 18:11 Alarig Le Lay via Bird-users <<a href="mailto:bird-users@network.cz">bird-users@network.cz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
We (Evann and I) found a bug related to as_path_getlen() when used by<br>
aspa_check(). When a route contains an AS_SET segment type, the length<br>
returned by as_path_getlen() is incorrect. The function assumes that the<br>
length of an AS_PATH_SET is a single AS (1), while in reality an<br>
AS_PATH_SET is an unordered set of ASN (as described here<br>
<a href="https://www.rfc-editor.org/rfc/rfc4271#section-9.2.2.1" rel="noreferrer noreferrer" target="_blank">https://www.rfc-editor.org/rfc/rfc4271#section-9.2.2.1</a>).<br>
<br>
See the following update:<br>
2025-08-31 15:35:15.134 <INFO> Checking prefix <a href="http://76.165.0.0/16" rel="noreferrer noreferrer" target="_blank">76.165.0.0/16</a> (path 208627 29075 174 32440 {2055 10349 22985 23207 23294 23366 26002 26303 26333 30564 54529 396992 401290}) IN from bgp_alarig_ipv4<br>
<br>
Using gdb we can inspect the path object:<br>
(gdb) p path->length <br>
$101 = 72<br>
(gdb) x /72xb path->data<br>
0x555555725e54: 0x02 0x04 0x00 0x03 0x2e 0xf3 0x00 0x00<br>
0x555555725e5c: 0x71 0x93 0x00 0x00 0x00 0xae 0x00 0x00<br>
0x555555725e64: 0x7e 0xb8 0x01 0x0d 0x00 0x00 0x08 0x07<br>
0x555555725e6c: 0x00 0x00 0x28 0x6d 0x00 0x00 0x59 0xc9<br>
0x555555725e74: 0x00 0x00 0x5a 0xa7 0x00 0x00 0x5a 0xfe<br>
0x555555725e7c: 0x00 0x00 0x5b 0x46 0x00 0x00 0x65 0x92<br>
0x555555725e84: 0x00 0x00 0x66 0xbf 0x00 0x00 0x66 0xdd<br>
0x555555725e8c: 0x00 0x00 0x77 0x64 0x00 0x00 0xd5 0x01<br>
0x555555725e94: 0x00 0x06 0x0e 0xc0 0x00 0x06 0x1f 0x8a<br>
<br>
In this example, we have a route with an AS_PATH that contain:<br>
- an AS_PATH_SEQUENCE (0x02) with a length of 4 (0x04): (208627<br>
29075 174 32440);<br>
- an AS_PATH_SET (0x01) with a length of 13 (0x0d): {2055 10349<br>
22985 23207 23294 23366 26002 26303 26333 30564 54529 396992<br>
401290}.<br>
The total length of this update is then 17, but if we dump the function<br>
result, we can see that the actual computed length is 5 (4 + 1 for the<br>
AS_PATH_SET).<br>
(gdb) p len<br>
$103 = 5<br>
<br>
This leads to a too small memory allocation, when normalizing the AS<br>
Path in aspa_check():<br>
/* Normalize the AS Path: drop stuffings */<br>
u32 *asns = alloca(sizeof(u32) * len);<br>
Causing a SEGFAULT during the as path walk. Since as_path_walk()<br>
considers each element of the AS_PATH_SET as a step. In the while<br>
(as_path_walk(path, &ppos, &asns[nsz])), the asns object should have a<br>
size of 17 and not 5 resulting in overwriting memory and finally<br>
triggering a SEGFAULT. (However we've seen this working when the AS_SET<br>
is small, for example, it's working for the following route, but this is<br>
mostly luck and could lead to weird behaviors): <br>
Checking prefix <a href="http://104.141.0.0/16" rel="noreferrer noreferrer" target="_blank">104.141.0.0/16</a> (path 208627 29075 174 32440 {400943}) IN from bgp_alarig_ipv4<br>
<br>
Here is the gdb output showing this behaviour:<br>
2025-08-31 15:35:15.134 <TRACE> bgp_alarig_ipv4: Got UPDATE<br>
2025-08-31 15:35:15.134 <INFO> Checking prefix <a href="http://76.165.0.0/16" rel="noreferrer noreferrer" target="_blank">76.165.0.0/16</a> (path 208627 29075 174 32440 {2055 10349 22985 23207 23294 23366 26002 26303 26333 30564 54529 396992 401290}) IN from bgp_alarig_ipv4<br>
<br>
Thread 1 "bird" received signal SIGSEGV, Segmentation fault.<br>
0x00005555555d68ac in as_path_walk (path=0x5555000066dd, pos=0x7fffffffd15c, <br>
val=0x7fffffffd144) at nest/a-path.c:702<br>
702 const u8 *q = p + path->length;<br>
(gdb) p path->data<br>
$1 = 0x5555000066e1 <error: Cannot access memory at address 0x5555000066e1><br>
<br>
And here is a dump of asns just before the segfault : <br>
(gdb) p *asns@nsz+1<br>
$57 = {208627, 29075, 174, 32440, 2055, 10349, 22985, 23207, 23294, 23366, 26002, 26303, <br>
26333}<br>
<br>
We propose to set the AS_PATH_SET length to the announced length in the<br>
AS_PATH data instead of 1, see<br>
0001-NEST-correct-as_path-len-calculation.patch.<br>
<br>
Furthermore, as per<br>
<a href="https://datatracker.ietf.org/doc/html/rfc9774#name-updates-to-the-requirements" rel="noreferrer noreferrer" target="_blank">https://datatracker.ietf.org/doc/html/rfc9774#name-updates-to-the-requirements</a><br>
(BGP speakers MUST use the "treat-as-withdraw" error handling behavior<br>
per [RFC7606] upon reception of BGP UPDATE messages containing AS_SETs<br>
or AS_CONFED_SETs in the AS_PATH or AS4_PATH [RFC6793]) and even if<br>
<a href="https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification-22#name-as_path-verification" rel="noreferrer noreferrer" target="_blank">https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification-22#name-as_path-verification</a><br>
changes it to a SHOULD, another improvement we propose is to check for<br>
AS_PATH_SET the same way it’s already done for AS_PATH_CONFED_SEQUENCE<br>
and AS_PATH_CONFED_SET at the beginning of the aspa_check() (see<br>
0002-NEST-return-ASPA_INVALID-for-path-containing-AS_SET.patch). The<br>
proposed patch is only for ASPA, not for ROV, in order to avoid dropping<br>
routes for too much people, and the patch only drop a few amounts of<br>
routes (including a few routes dropped for invalid ROV) :<br>
Routes: 1031692 imported, 212 filtered, 0 exported, 1031692 preferred<br>
<br>
Don’t hesitate to discuss the patch if needed,<br>
-- <br>
Alarig and Evann<br>
</blockquote></div>