From 5eea2640324928c15936b7a2bcbf8ea0de7b08f7 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-Status: Backport [https://github.com/avahi/avahi/commit/78eab31128479f06e30beb8c1cbf99dd921e2524] (cherry picked from commit 78eab31128479f06e30beb8c1cbf99dd921e2524) Signed-off-by: Ankur Tyagi --- avahi-core/browse.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/avahi-core/browse.c b/avahi-core/browse.c index f461083..975b3e9 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);