From 93012b3ac81bc8e2a0a9b7e48b552c269b0523d9 Mon Sep 17 00:00:00 2001 From: Evann DREUMONT <53308142+LeGmask@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:23:34 +0200 Subject: [PATCH] Nest: Function aspa_check() should return ASPA_INVALID for paths containing AS_SET 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 Minor changes by committer. --- nest/a-path.c | 21 +++++++++++++++++++++ nest/attrs.h | 1 + nest/rt-table.c | 7 ++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/nest/a-path.c b/nest/a-path.c index aba2c86df..6f52ccf6a 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -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) { diff --git a/nest/attrs.h b/nest/attrs.h index 0475afa72..699b91df2 100644 --- a/nest/attrs.h +++ b/nest/attrs.h @@ -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); diff --git a/nest/rt-table.c b/nest/rt-table.c index ee3f11882..ed364d351 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -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; -- 2.47.3