| From 78eab31128479f06e30beb8c1cbf99dd921e2524 Mon Sep 17 00:00:00 2001 |
| From: Hugo Muis <198191869+friendlyhugo@users.noreply.github.com> |
| Date: Sun, 2 Mar 2025 18:06:24 +0100 |
| Subject: [PATCH] core: fix uncontrolled recursion bug using a simple loop |
| detection algorithm |
| |
| Closes https://github.com/avahi/avahi/issues/501 |
| |
| CVE: CVE-2026-24401 |
| Upstream: https://github.com/avahi/avahi/commit/78eab31128479f06e30beb8c1cbf99dd921e2524 |
| Signed-off-by: Thomas Perale <thomas.perale@mind.be> |
| --- |
| avahi-core/browse.c | 40 ++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 40 insertions(+) |
| |
| diff --git a/avahi-core/browse.c b/avahi-core/browse.c |
| index ad08bd65f..e00cbed84 100644 |
| --- a/avahi-core/browse.c |
| +++ b/avahi-core/browse.c |
| @@ -401,6 +401,40 @@ static int lookup_go(AvahiSRBLookup *l) { |
| return n; |
| } |
| |
| +static int lookup_exists_in_path(AvahiSRBLookup* lookup, AvahiSRBLookup* from, AvahiSRBLookup* to) { |
| + AvahiRList* rl; |
| + if (from == to) |
| + return 0; |
| + for (rl = from->cname_lookups; rl; rl = rl->rlist_next) { |
| + int r = lookup_exists_in_path(lookup, rl->data, to); |
| + if (r == 1) { |
| + /* loop detected, propagate result */ |
| + return r; |
| + } else if (r == 0) { |
| + /* is loop detected? */ |
| + return lookup == from; |
| + } else { |
| + /* `to` not found, continue */ |
| + continue; |
| + } |
| + } |
| + /* no path found */ |
| + return -1; |
| +} |
| + |
| +static int cname_would_create_loop(AvahiSRBLookup* l, AvahiSRBLookup* n) { |
| + int ret; |
| + if (l == n) |
| + /* Loop to self */ |
| + return 1; |
| + |
| + ret = lookup_exists_in_path(n, l->record_browser->root_lookup, l); |
| + |
| + /* Path to n always exists */ |
| + assert(ret != -1); |
| + return ret; |
| +} |
| + |
| static void lookup_handle_cname(AvahiSRBLookup *l, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiRecord *r) { |
| AvahiKey *k; |
| AvahiSRBLookup *n; |
| @@ -420,6 +454,12 @@ static void lookup_handle_cname(AvahiSRBLookup *l, AvahiIfIndex interface, Avahi |
| return; |
| } |
| |
| + if (cname_would_create_loop(l, n)) { |
| + /* CNAME loops are not allowed */ |
| + lookup_unref(n); |
| + return; |
| + } |
| + |
| l->cname_lookups = avahi_rlist_prepend(l->cname_lookups, lookup_ref(n)); |
| |
| lookup_go(n); |