<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hello!<br>
      <br>
      Yes, I can confirm that, especially with the new RFC 9774
      standard, see
      <a class="moz-txt-link-freetext" href="https://datatracker.ietf.org/doc/html/rfc9774#section-4">https://datatracker.ietf.org/doc/html/rfc9774#section-4</a>.<br>
      That something we address in the second patch.<br>
      <br>
      Originally, the segfault was handled by returning ASPA_INVALID on
      AS_PATH that contained an AS\_SET, but we discovered that this was
      not the real problem, but rather a bad allocation due to an
      incorrect calculation of the AS path length. We mitigated this
      issue with our first patch.<br>
      <br>
      Best, <br>
      --<br>
      Evann & Alarig<br>
      <br>
    </p>
    <div class="moz-cite-prefix">On 8/31/25 8:02 PM, Alexander Zubkov
      via Bird-users wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CABr+u0ayEwUypz0O_YyJsALNwk86fDUw-UNzn+vRup0M=df3dw@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <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"
            moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true"
            class="moz-txt-link-freetext">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"
            moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true">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"
            moz-do-not-send="true">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" moz-do-not-send="true">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"
            moz-do-not-send="true" class="moz-txt-link-freetext">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"
            moz-do-not-send="true" class="moz-txt-link-freetext">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>
    </blockquote>
  </body>
</html>