]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Function aspa_check() should return ASPA_INVALID for paths containing AS_SET
authorEvann DREUMONT <53308142+LeGmask@users.noreply.github.com>
Tue, 2 Sep 2025 14:23:34 +0000 (16:23 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 3 Sep 2025 13:57:56 +0000 (15:57 +0200)
The aspa_check() uses as_path_getlen() to estimate the size of a buffer,
which does not work for AS_SET segments, because as_path_getlen() returns
length 1 for them regardless of their length. This may cause buffer
overflow and crash.

As AS_SET segments are not valid for ASPA verification, we can just
handle them explicitly. See https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-aspa-verification#section-6

Co-Authored-By: Alarig <alarig@swordarmor.fr>
Minor changes by committer.

lib/a-path.c
lib/attrs.h
nest/rt-table.c

index acbc240576933b67c83ad3bbc93ce6cb210c80be..b87422b6dc04dd783d217c4c296f9a22d25f9ca8 100644 (file)
@@ -177,6 +177,27 @@ as_path_contains_confed(const struct adata *path)
   return 0;
 }
 
+int
+as_path_contains_set(const struct adata *path)
+{
+  const byte *pos = path->data;
+  const byte *end = pos + path->length;
+
+  while (pos < end)
+  {
+    uint type = pos[0];
+    uint slen = 2 + BS * pos[1];
+
+    if ((type == AS_PATH_SET) ||
+       (type == AS_PATH_CONFED_SET))
+      return 1;
+
+    pos += slen;
+  }
+
+  return 0;
+}
+
 struct adata *
 as_path_strip_confed(struct linpool *pool, const struct adata *path)
 {
index b57348d5ae2f887d126b9d9dcf759ae5d159c443..ba2e0a83a513cbae15819523afd3274af1a46adb 100644 (file)
@@ -69,6 +69,7 @@ int as_path_16to32(byte *dst, const byte *src, uint len);
 int as_path_32to16(byte *dst, const byte *src, uint len);
 int as_path_contains_as4(const struct adata *path);
 int as_path_contains_confed(const struct adata *path);
+int as_path_contains_set(const struct adata *path);
 struct adata *as_path_strip_confed(struct linpool *pool, const struct adata *op);
 struct adata *as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as);
 struct adata *as_path_to_old(struct linpool *pool, const struct adata *path);
index cc79be1935a7ed1865be910f2b7e24e2b1504c47..5f42bf983cc9ea567e09fc777d728b32cabeb64e 100644 (file)
@@ -733,7 +733,12 @@ enum aspa_result aspa_check(rtable *tab, const adata *path, bool force_upstream)
   if (as_path_contains_confed(path))
     return ASPA_INVALID;
 
-  /* Check path length */
+  /* No support for AS_SET */
+  /* See draft-ietf-sidrops-aspa-verification section 6 */
+  if (as_path_contains_set(path))
+    return ASPA_INVALID;
+
+  /* Check path length; we assume just AS_SEQUENCE segments */
   uint len = as_path_getlen(path);
   if (len == 0)
     return ASPA_INVALID;