]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Nest: Function aspa_check() should return ASPA_INVALID for paths containing AS_SET master
authorEvann DREUMONT <53308142+LeGmask@users.noreply.github.com>
Tue, 2 Sep 2025 14:23:34 +0000 (16:23 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 2 Sep 2025 14:23:34 +0000 (16:23 +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.

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

index aba2c86df0005f7e5e7e4cbd4396fa629587d62c..6f52ccf6aefd859b70d340c07f46d887c20d7e42 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 0475afa72c8f2f7239e760f5a395c8c05c64acb3..699b91df28c38e264249b2b6ab3d205e7e2fbd07 100644 (file)
@@ -36,6 +36,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 ee3f11882fd613c43eb4c87be9e9f5217d9699fc..ed364d3510c40a951cce172d103e70f78385b8fe 100644 (file)
@@ -362,7 +362,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;