avahi: update to 0.9-rc4

Fixes https://github.com/openwrt/packages/issues/27952

Update avahi from 0.8 to 0.9-rc4. The 0.9 development line accumulates
four years of bug and security fixes since the 0.8 release (2020-02-18).

Notable improvements in 0.9-rc4 over 0.8:

Security (all CVEs previously backported as patches, now removed):
  - CVE-2023-38469: reject TXT records whose total rdata exceeds
    AVAHI_DNS_RDATA_MAX, preventing heap-buffer reads under crafted mDNS
  - CVE-2023-38470: ensure each DNS label is at least one byte, preventing
    an infinite loop on malformed packets
  - CVE-2023-38471: extract host name via avahi_unescape_label() before
    generating an alternative to avoid operating on a raw escaped string
  - CVE-2023-38472: check that rdata pointer is non-NULL before passing to
    avahi_rdata_parse() from dbus-entry-group
  - CVE-2023-38473: derive alternative host name from its unescaped form,
    fixing incorrect hostname collision resolution with escaped labels

Bug fixes (previously backported):
  - Fix NULL-pointer crashes in avahi_s_*_browser_new() (#175)
  - Avoid infinite loop in avahi-daemon simple-protocol by handling
    AVAHI_WATCH_HUP event in client_work
  - Fix potential undefined behaviour in avahi_dns_packet_consume_uint32:
    cast uint8_t operands to uint32_t before shifting
  - Fix memory/CPU leak in the simple event loop: cleanup_watches() was
    zeroing timeout_req_cleanup instead of watch_req_cleanup, so completed
    watches were never removed from the linked list
  - Emit D-Bus error reply when avahi-daemon cannot resolve a hostname or
    service, rather than crashing with a NULL dereference
  - Increase ini-file-parser line buffer from 256 to 1024 bytes to handle
    longer configuration values without silent truncation

Other changes:
  - P2P tunnel support: IFF_MULTICAST is no longer required for
    point-to-point interfaces when allow-point-to-point=yes
  - Runtime directory: configure.ac now derives the socket path from
    ${runstatedir} (defaults to ${localstatedir}/run), so the
    explicit patch reverting the /run hardcoding is no longer needed
  - Patch 010-pkgconfig.patch (pkgconfig prefix alignment) is retained
    as it has not been merged upstream

Dropped patches (all merged upstream):
  020-revert-runtime-dir-systemd-change.patch
  100-p2p-no-iff_multicast-required.patch
  200-Fix-NULL-pointer-crashes-from-175.patch
  201-Avoid-infinite-loop-in-avahi-daemon-by-handling-HUP-event.patch
  202-avahi_dns_packet_consume_uint32-fix-potential-undefined-b.patch
  203-Do-not-disable-timeout-cleanup-on-watch-cleanup.patch
  204-Emit-error-if-requested-service-is-not-found.patch
  205-conf-file-line-lengths.patch
  300-CVE-2023-38469.patch through 304-CVE-2023-38473.patch

Library SONAMES unchanged: libavahi-common.so.3, libavahi-core.so.7,
libavahi-client.so.3 — no reverse dependency rebuilds required.

Disable libsystemd (not available on OpenWrt)
avahi 0.9-rc4 added --enable-libsystemd which defaults to enabled and
fails configure when libsystemd is not found via pkg-config.  OpenWrt
does not provide libsystemd; disable it explicitly.
Also pass --with-systemdsystemunitdir=no to suppress the pkg-config
lookup for the systemd unit directory.

Drop po/ subdir from build
The 0.9-rc4 tarball is a raw git archive; po/Makefile.in.in is not
pre-generated as it was in the 0.8 release tarball.  autopoint (from
gettext) is needed to install it, but is not available in the OpenWrt
SDK.  Since OpenWrt does not use NLS translations, remove po/ from
SUBDIRS in Makefile.am to avoid the missing po/Makefile.in.in error
during configure.

In 0.9-rc4 the D-Bus system.d directory changed from
$(sysconfdir)/dbus-1/system.d to $(datadir)/dbus-1/system.d,
so avahi-dbus.conf is now installed under usr/share/dbus-1/system.d.
Update the install rule source path accordingly; keep the on-device
destination at /etc/dbus-1/system.d for compatibility.

Signed-off-by: Alexandru Ardelean <alex@shruggie.ro>
(cherry picked from commit 24c3026f94)
This commit is contained in:
Alexandru Ardelean
2026-05-05 09:49:32 +03:00
committed by Alexandru Ardelean
parent d9148ab2ae
commit 5ab103ce37
16 changed files with 244 additions and 640 deletions
+9 -7
View File
@@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=avahi
PKG_VERSION:=0.8
PKG_RELEASE:=9
PKG_VERSION:=0.9_rc4
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/lathiat/avahi/releases/download/v$(PKG_VERSION) \
https://avahi.org/download
PKG_HASH:=060309d7a333d38d951bc27598c677af1796934dbd98e1024e7ad8de798fedda
PKG_SOURCE:=$(PKG_NAME)-0.9-rc4.tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/avahi/avahi/tar.gz/v0.9-rc4?
PKG_HASH:=08fcc57377ed05416ec4b3d8a179da716a7a9376821551a5ae16f8276a1ef0b5
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-0.9-rc4
PKG_MAINTAINER:=Ted Hess <thess@kitschensync.net>
PKG_LICENSE:=LGPL-2.1-or-later
@@ -268,6 +268,8 @@ CONFIGURE_ARGS += \
--disable-manpages \
--disable-xmltoman \
--disable-tests \
--disable-libsystemd \
--with-systemdsystemunitdir=no \
--with-xml=expat \
--with-distro=none \
--with-avahi-user=nobody \
@@ -305,7 +307,7 @@ endef
define Package/libavahi-dbus-support/install
$(call Package/libavahi/install,$(1))
$(INSTALL_DIR) $(1)/etc/dbus-1/system.d
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/etc/dbus-1/system.d/* $(1)/etc/dbus-1/system.d
$(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/share/dbus-1/system.d/* $(1)/etc/dbus-1/system.d
endef
Package/libavahi-nodbus-support/install=$(Package/libavahi/install)
+31
View File
@@ -0,0 +1,31 @@
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,8 +78,7 @@ SUBDIRS = \
avahi-autoipd \
avahi-ui \
avahi-ui-sharp \
- avahi-libevent \
- po
+ avahi-libevent
DX_INPUT = \
$(srcdir)/avahi-common/address.h \
--- a/configure.ac
+++ b/configure.ac
@@ -425,8 +425,6 @@ fi
GETTEXT_PACKAGE=avahi
AC_SUBST([GETTEXT_PACKAGE])
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[Gettext package])
-AM_GNU_GETTEXT_VERSION([0.19.8])
-AM_GNU_GETTEXT([external])
# Check for pkg-config manually first, as if its not installed the
# PKG_PROG_PKG_CONFIG macro won't be defined.
@@ -1177,7 +1175,6 @@ avahi-compat-howl/samples/Makefile
avahi-autoipd/Makefile
avahi-ui/Makefile
avahi-libevent/Makefile
-po/Makefile.in
])
AC_OUTPUT
@@ -1,11 +0,0 @@
--- a/configure.ac
+++ b/configure.ac
@@ -1004,7 +1004,7 @@ AC_DEFINE_UNQUOTED(AVAHI_AUTOIPD_GROUP,"
#
# Avahi runtime dir
#
-avahi_runtime_dir="/run"
+avahi_runtime_dir="${localstatedir}/run"
avahi_socket="${avahi_runtime_dir}/avahi-daemon/socket"
AC_SUBST(avahi_runtime_dir)
AC_SUBST(avahi_socket)
@@ -1,45 +0,0 @@
commit 2b6bccca5d9d8ab7f11219a639707b325910a0b1
Author: Philip Prindeville <philipp@redfish-solutions.com>
Date: Thu Sep 17 00:27:55 2020 +0000
Logic for p2p on tunnels incorrectly requires IFF_MULTICAST (#305)
Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
--- a/avahi-core/iface-linux.c
+++ b/avahi-core/iface-linux.c
@@ -105,8 +105,8 @@ static void netlink_callback(AvahiNetlin
(ifinfomsg->ifi_flags & IFF_UP) &&
(!m->server->config.use_iff_running || (ifinfomsg->ifi_flags & IFF_RUNNING)) &&
((ifinfomsg->ifi_flags & IFF_LOOPBACK) ||
- (ifinfomsg->ifi_flags & IFF_MULTICAST)) &&
- (m->server->config.allow_point_to_point || !(ifinfomsg->ifi_flags & IFF_POINTOPOINT));
+ (ifinfomsg->ifi_flags & IFF_MULTICAST) ||
+ ((ifinfomsg->ifi_flags & IFF_POINTOPOINT) && m->server->config.allow_point_to_point));
/* Handle interface attributes */
l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
--- a/avahi-core/iface-pfroute.c
+++ b/avahi-core/iface-pfroute.c
@@ -81,8 +81,8 @@ static void rtm_info(struct rt_msghdr *r
(ifm->ifm_flags & IFF_UP) &&
(!m->server->config.use_iff_running || (ifm->ifm_flags & IFF_RUNNING)) &&
((ifm->ifm_flags & IFF_LOOPBACK) ||
- (ifm->ifm_flags & IFF_MULTICAST)) &&
- (m->server->config.allow_point_to_point || !(ifm->ifm_flags & IFF_POINTOPOINT));
+ (ifm->ifm_flags & IFF_MULTICAST) ||
+ ((ifm->ifm_flags & IFF_POINTOPOINT) && m->server->config.allow_point_to_point));
avahi_free(hw->name);
hw->name = avahi_strndup(sdl->sdl_data, sdl->sdl_nlen);
@@ -428,8 +428,8 @@ static void if_add_interface(struct lifr
(flags & IFF_UP) &&
(!m->server->config.use_iff_running || (flags & IFF_RUNNING)) &&
((flags & IFF_LOOPBACK) ||
- (flags & IFF_MULTICAST)) &&
- (m->server->config.allow_point_to_point || !(flags & IFF_POINTOPOINT));
+ (flags & IFF_MULTICAST) ||
+ ((flags & IFF_POINTOPOINT) && m->server->config.allow_point_to_point));
hw->name = avahi_strdup(lifreq->lifr_name);
hw->mtu = mtu;
/* TODO get mac address */
@@ -1,136 +0,0 @@
From 9d31939e55280a733d930b15ac9e4dda4497680c Mon Sep 17 00:00:00 2001
From: Tommi Rantala <tommi.t.rantala@nokia.com>
Date: Mon, 8 Feb 2021 11:04:43 +0200
Subject: [PATCH] Fix NULL pointer crashes from #175
avahi-daemon is crashing when running "ping .local".
The crash is due to failing assertion from NULL pointer.
Add missing NULL pointer checks to fix it.
Introduced in #175 - merge commit 8f75a045709a780c8cf92a6a21e9d35b593bdecd
[Retrieved from:
https://github.com/lathiat/avahi/commit/9d31939e55280a733d930b15ac9e4dda4497680c]
Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
---
avahi-core/browse-dns-server.c | 5 ++++-
avahi-core/browse-domain.c | 5 ++++-
avahi-core/browse-service-type.c | 3 +++
avahi-core/browse-service.c | 3 +++
avahi-core/browse.c | 3 +++
avahi-core/resolve-address.c | 5 ++++-
avahi-core/resolve-host-name.c | 5 ++++-
avahi-core/resolve-service.c | 5 ++++-
8 files changed, 29 insertions(+), 5 deletions(-)
--- a/avahi-core/browse-dns-server.c
+++ b/avahi-core/browse-dns-server.c
@@ -343,7 +343,10 @@ AvahiSDNSServerBrowser *avahi_s_dns_serv
AvahiSDNSServerBrowser* b;
b = avahi_s_dns_server_browser_prepare(server, interface, protocol, domain, type, aprotocol, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_dns_server_browser_start(b);
return b;
-}
\ No newline at end of file
+}
--- a/avahi-core/browse-domain.c
+++ b/avahi-core/browse-domain.c
@@ -253,7 +253,10 @@ AvahiSDomainBrowser *avahi_s_domain_brow
AvahiSDomainBrowser *b;
b = avahi_s_domain_browser_prepare(server, interface, protocol, domain, type, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_domain_browser_start(b);
return b;
-}
\ No newline at end of file
+}
--- a/avahi-core/browse-service-type.c
+++ b/avahi-core/browse-service-type.c
@@ -171,6 +171,9 @@ AvahiSServiceTypeBrowser *avahi_s_servic
AvahiSServiceTypeBrowser *b;
b = avahi_s_service_type_browser_prepare(server, interface, protocol, domain, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_service_type_browser_start(b);
return b;
--- a/avahi-core/browse-service.c
+++ b/avahi-core/browse-service.c
@@ -184,6 +184,9 @@ AvahiSServiceBrowser *avahi_s_service_br
AvahiSServiceBrowser *b;
b = avahi_s_service_browser_prepare(server, interface, protocol, service_type, domain, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_service_browser_start(b);
return b;
--- a/avahi-core/browse.c
+++ b/avahi-core/browse.c
@@ -634,6 +634,9 @@ AvahiSRecordBrowser *avahi_s_record_brow
AvahiSRecordBrowser *b;
b = avahi_s_record_browser_prepare(server, interface, protocol, key, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_record_browser_start_query(b);
return b;
--- a/avahi-core/resolve-address.c
+++ b/avahi-core/resolve-address.c
@@ -286,7 +286,10 @@ AvahiSAddressResolver *avahi_s_address_r
AvahiSAddressResolver *b;
b = avahi_s_address_resolver_prepare(server, interface, protocol, address, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_address_resolver_start(b);
return b;
-}
\ No newline at end of file
+}
--- a/avahi-core/resolve-host-name.c
+++ b/avahi-core/resolve-host-name.c
@@ -318,7 +318,10 @@ AvahiSHostNameResolver *avahi_s_host_nam
AvahiSHostNameResolver *b;
b = avahi_s_host_name_resolver_prepare(server, interface, protocol, host_name, aprotocol, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_host_name_resolver_start(b);
return b;
-}
\ No newline at end of file
+}
--- a/avahi-core/resolve-service.c
+++ b/avahi-core/resolve-service.c
@@ -519,7 +519,10 @@ AvahiSServiceResolver *avahi_s_service_r
AvahiSServiceResolver *b;
b = avahi_s_service_resolver_prepare(server, interface, protocol, name, type, domain, aprotocol, flags, callback, userdata);
+ if (!b)
+ return NULL;
+
avahi_s_service_resolver_start(b);
return b;
-}
\ No newline at end of file
+}
@@ -1,36 +0,0 @@
From: Riccardo Schirone <sirmy15@gmail.com>
Date: Fri, 26 Mar 2021 11:50:24 +0100
Subject: Avoid infinite-loop in avahi-daemon by handling HUP event in
client_work
If a client fills the input buffer, client_work() disables the
AVAHI_WATCH_IN event, thus preventing the function from executing the
`read` syscall the next times it is called. However, if the client then
terminates the connection, the socket file descriptor receives a HUP
event, which is not handled, thus the kernel keeps marking the HUP event
as occurring. While iterating over the file descriptors that triggered
an event, the client file descriptor will keep having the HUP event and
the client_work() function is always called with AVAHI_WATCH_HUP but
without nothing being done, thus entering an infinite loop.
See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=984938
(cherry picked from commit 447affe29991ee99c6b9732fc5f2c1048a611d3b)
---
avahi-daemon/simple-protocol.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/avahi-daemon/simple-protocol.c
+++ b/avahi-daemon/simple-protocol.c
@@ -424,6 +424,11 @@ static void client_work(AvahiWatch *watc
}
}
+ if (events & AVAHI_WATCH_HUP) {
+ client_free(c);
+ return;
+ }
+
c->server->poll_api->watch_update(
watch,
(c->outbuf_length > 0 ? AVAHI_WATCH_OUT : 0) |
@@ -1,27 +0,0 @@
From: traffic-millions <60914101+traffic-millions@users.noreply.github.com>
Date: Tue, 3 Mar 2020 11:15:48 +0800
Subject: avahi_dns_packet_consume_uint32: fix potential undefined behavior
avahi_dns_packet_consume_uint32 left shifts uint8_t values by 8, 16 and 24 bits to combine them into a 32-bit value. This produces an undefined behavior warning with gcc -fsanitize when fed input values of 128 or 255 however in testing no actual unexpected behavior occurs in practice and the 32-bit uint32_t is always correctly produced as the final value is immediately stored into a uint32_t and the compiler appears to handle this "correctly".
Cast the intermediate values to uint32_t to prevent this warning and ensure the intended result is explicit.
Closes: #267
Closes: #268
Reference: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19304
Origin: upstream, 0.9, commit:b897ca43ac100d326d118e5877da710eb7f836f9
---
avahi-core/dns.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/avahi-core/dns.c
+++ b/avahi-core/dns.c
@@ -455,7 +455,7 @@ int avahi_dns_packet_consume_uint32(Avah
return -1;
d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
- *ret_v = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+ *ret_v = ((uint32_t)d[0] << 24) | ((uint32_t)d[1] << 16) | ((uint32_t)d[2] << 8) | (uint32_t)d[3];
p->rindex += sizeof(uint32_t);
return 0;
@@ -1,22 +0,0 @@
From: Gustavo Noronha Silva <gustavo@noronha.dev.br>
Date: Sun, 2 Jan 2022 22:29:04 -0300
Subject: Do not disable timeout cleanup on watch cleanup
This was causing timeouts to never be removed from the linked list that
tracks them, resulting in both memory and CPU usage to grow larger over
time.
---
avahi-common/simple-watch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/avahi-common/simple-watch.c
+++ b/avahi-common/simple-watch.c
@@ -238,7 +238,7 @@ static void cleanup_watches(AvahiSimpleP
destroy_watch(w);
}
- s->timeout_req_cleanup = 0;
+ s->watch_req_cleanup = 0;
}
static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) {
@@ -1,54 +0,0 @@
From: =?utf-8?b?UGV0ciBNZW7FocOtaw==?= <pemensik@redhat.com>
Date: Thu, 17 Nov 2022 01:51:53 +0100
Subject: Emit error if requested service is not found
It currently just crashes instead of replying with error. Check return
value and emit error instead of passing NULL pointer to reply.
Fixes #375
(cherry picked from commit a2696da2f2c50ac43b6c4903f72290d5c3fa9f6f)
---
avahi-daemon/dbus-protocol.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
--- a/avahi-daemon/dbus-protocol.c
+++ b/avahi-daemon/dbus-protocol.c
@@ -375,10 +375,14 @@ static DBusHandlerResult dbus_get_altern
}
t = avahi_alternative_host_name(n);
- avahi_dbus_respond_string(c, m, t);
- avahi_free(t);
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (t) {
+ avahi_dbus_respond_string(c, m, t);
+ avahi_free(t);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else {
+ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Hostname not found");
+ }
}
static DBusHandlerResult dbus_get_alternative_service_name(DBusConnection *c, DBusMessage *m, DBusError *error) {
@@ -389,10 +393,14 @@ static DBusHandlerResult dbus_get_altern
}
t = avahi_alternative_service_name(n);
- avahi_dbus_respond_string(c, m, t);
- avahi_free(t);
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (t) {
+ avahi_dbus_respond_string(c, m, t);
+ avahi_free(t);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ } else {
+ return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_FOUND, "Service not found");
+ }
}
static DBusHandlerResult dbus_create_new_entry_group(DBusConnection *c, DBusMessage *m, DBusError *error) {
@@ -1,11 +0,0 @@
--- a/avahi-daemon/ini-file-parser.c
+++ b/avahi-daemon/ini-file-parser.c
@@ -50,7 +50,7 @@ AvahiIniFile* avahi_ini_file_load(const
line = 0;
while (!feof(fo)) {
- char ln[256], *s, *e;
+ char ln[1024], *s, *e;
AvahiIniFilePair *pair;
if (!(fgets(ln, sizeof(ln), fo)))
@@ -1,41 +0,0 @@
From a337a1ba7d15853fb56deef1f464529af6e3a1cf Mon Sep 17 00:00:00 2001
From: Evgeny Vereshchagin <evvers@ya.ru>
Date: Mon, 23 Oct 2023 20:29:31 +0000
Subject: [PATCH] core: reject overly long TXT resource records
Closes https://github.com/lathiat/avahi/issues/455
CVE-2023-38469
---
avahi-core/rr.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/avahi-core/rr.c
+++ b/avahi-core/rr.c
@@ -32,6 +32,7 @@
#include <avahi-common/malloc.h>
#include <avahi-common/defs.h>
+#include "dns.h"
#include "rr.h"
#include "log.h"
#include "util.h"
@@ -688,11 +689,17 @@ int avahi_record_is_valid(AvahiRecord *r
case AVAHI_DNS_TYPE_TXT: {
AvahiStringList *strlst;
+ size_t used = 0;
- for (strlst = r->data.txt.string_list; strlst; strlst = strlst->next)
+ for (strlst = r->data.txt.string_list; strlst; strlst = strlst->next) {
if (strlst->size > 255 || strlst->size <= 0)
return 0;
+ used += 1+strlst->size;
+ if (used > AVAHI_DNS_RDATA_MAX)
+ return 0;
+ }
+
return 1;
}
}
@@ -1,48 +0,0 @@
From b6cf29f98adce7355e8c51a6af1e338a5f94e16e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
Date: Tue, 11 Apr 2023 15:29:59 +0200
Subject: [PATCH] Ensure each label is at least one byte long
The only allowed exception is single dot, where it should return empty
string.
Fixes #454.
---
avahi-common/domain-test.c | 14 ++++++++++++++
avahi-common/domain.c | 2 +-
2 files changed, 15 insertions(+), 1 deletion(-)
--- a/avahi-common/domain-test.c
+++ b/avahi-common/domain-test.c
@@ -45,6 +45,20 @@ int main(AVAHI_GCC_UNUSED int argc, AVAH
printf("%s\n", s = avahi_normalize_name_strdup("fo\\\\o\\..f oo."));
avahi_free(s);
+ printf("%s\n", s = avahi_normalize_name_strdup("."));
+ avahi_free(s);
+
+ s = avahi_normalize_name_strdup(",.=.}.=.?-.}.=.?.?.}.}.?.?.?.z.?.?.}.}."
+ "}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.=.=.?.?.}.}.?.?.}.}.}"
+ ".?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.=.=.?.?.}.}.?.?.?.zM.?`"
+ "?.}.}.}.?.?.?.r.=.?.}.=.?.?.}.?.?.?.}.=.?.?.}??.}.}.?.?."
+ "?.z.?.?.}.}.}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM.?`?.}.}.}."
+ "??.?.zM.?`?.}.}.}.?.?.?.r.=.?.}.=.?.?.}.?.?.?.}.=.?.?.}?"
+ "?.}.}.?.?.?.z.?.?.}.}.}.?.?.?.r.=.=.}.=.?.}}.}.?.?.?.zM."
+ "?`?.}.}.}.?.?.?.r.=.=.?.?`.?.?}.}.}.?.?.?.r.=.?.}.=.?.?."
+ "}.?.?.?.}.=.?.?.}");
+ assert(s == NULL);
+
printf("%i\n", avahi_domain_equal("\\065aa bbb\\.\\046cc.cc\\\\.dee.fff.", "Aaa BBB\\.\\.cc.cc\\\\.dee.fff"));
printf("%i\n", avahi_domain_equal("A", "a"));
--- a/avahi-common/domain.c
+++ b/avahi-common/domain.c
@@ -201,7 +201,7 @@ char *avahi_normalize_name(const char *s
}
if (!empty) {
- if (size < 1)
+ if (size < 2)
return NULL;
*(r++) = '.';
@@ -1,66 +0,0 @@
From d486bca7e7912c6a4b547a3c607db0d0d3124bbf Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 23 Oct 2023 13:38:35 +0200
Subject: [PATCH] core: extract host name using avahi_unescape_label()
Previously we could create invalid escape sequence when we split the
string on dot. For example, from valid host name "foo\\.bar" we have
created invalid name "foo\\" and tried to set that as the host name
which crashed the daemon.
Fixes #453
CVE-2023-38471
---
avahi-core/server.c | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
--- a/avahi-core/server.c
+++ b/avahi-core/server.c
@@ -1295,7 +1295,11 @@ static void update_fqdn(AvahiServer *s)
}
int avahi_server_set_host_name(AvahiServer *s, const char *host_name) {
- char *hn = NULL;
+ char label_escaped[AVAHI_LABEL_MAX*4+1];
+ char label[AVAHI_LABEL_MAX];
+ char *hn = NULL, *h;
+ size_t len;
+
assert(s);
AVAHI_CHECK_VALIDITY(s, !host_name || avahi_is_valid_host_name(host_name), AVAHI_ERR_INVALID_HOST_NAME);
@@ -1305,17 +1309,28 @@ int avahi_server_set_host_name(AvahiServ
else
hn = avahi_normalize_name_strdup(host_name);
- hn[strcspn(hn, ".")] = 0;
+ h = hn;
+ if (!avahi_unescape_label((const char **)&hn, label, sizeof(label))) {
+ avahi_free(h);
+ return AVAHI_ERR_INVALID_HOST_NAME;
+ }
+
+ avahi_free(h);
- if (avahi_domain_equal(s->host_name, hn) && s->state != AVAHI_SERVER_COLLISION) {
- avahi_free(hn);
+ h = label_escaped;
+ len = sizeof(label_escaped);
+ if (!avahi_escape_label(label, strlen(label), &h, &len))
+ return AVAHI_ERR_INVALID_HOST_NAME;
+
+ if (avahi_domain_equal(s->host_name, label_escaped) && s->state != AVAHI_SERVER_COLLISION)
return avahi_server_set_errno(s, AVAHI_ERR_NO_CHANGE);
- }
withdraw_host_rrs(s);
avahi_free(s->host_name);
- s->host_name = hn;
+ s->host_name = avahi_strdup(label_escaped);
+ if (!s->host_name)
+ return AVAHI_ERR_NO_MEMORY;
update_fqdn(s);
@@ -1,36 +0,0 @@
From d886dc5b1d3d2b76aaa38289245acfdfa979ca6c Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Thu, 19 Oct 2023 17:36:44 +0200
Subject: [PATCH] core: make sure there is rdata to process before parsing it
Fixes #452
CVE-2023-38472
---
avahi-client/client-test.c | 3 +++
avahi-daemon/dbus-entry-group.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
--- a/avahi-client/client-test.c
+++ b/avahi-client/client-test.c
@@ -258,6 +258,9 @@ int main (AVAHI_GCC_UNUSED int argc, AVA
printf("%s\n", avahi_strerror(avahi_entry_group_add_service (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "Lathiat's Site", "_http._tcp", NULL, NULL, 80, "foo=bar", NULL)));
printf("add_record: %d\n", avahi_entry_group_add_record (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "TestX", 0x01, 0x10, 120, "\5booya", 6));
+ error = avahi_entry_group_add_record (group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, "TestX", 0x01, 0x10, 120, "", 0);
+ assert(error != AVAHI_OK);
+
avahi_entry_group_commit (group);
domain = avahi_domain_browser_new (avahi, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, NULL, AVAHI_DOMAIN_BROWSER_BROWSE, 0, avahi_domain_browser_callback, (char*) "omghai3u");
--- a/avahi-daemon/dbus-entry-group.c
+++ b/avahi-daemon/dbus-entry-group.c
@@ -340,7 +340,7 @@ DBusHandlerResult avahi_dbus_msg_entry_g
if (!(r = avahi_record_new_full (name, clazz, type, ttl)))
return avahi_dbus_respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL);
- if (avahi_rdata_parse (r, rdata, size) < 0) {
+ if (!rdata || avahi_rdata_parse (r, rdata, size) < 0) {
avahi_record_unref (r);
return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL);
}
-100
View File
@@ -1,100 +0,0 @@
From 5edc17b7913cac824daa09fca9976c9c19e88822 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 11 Oct 2023 17:45:44 +0200
Subject: [PATCH] common: derive alternative host name from its unescaped
version
Normalization of input makes sure we don't have to deal with special
cases like unescaped dot at the end of label.
Fixes #451 #487
CVE-2023-38473
---
avahi-common/alternative-test.c | 3 +++
avahi-common/alternative.c | 27 +++++++++++++++++++--------
2 files changed, 22 insertions(+), 8 deletions(-)
--- a/avahi-common/alternative-test.c
+++ b/avahi-common/alternative-test.c
@@ -31,6 +31,9 @@ int main(AVAHI_GCC_UNUSED int argc, AVAH
const char* const test_strings[] = {
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXüüüüüüü",
+ ").",
+ "\\.",
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\\",
"gurke",
"-",
" #",
--- a/avahi-common/alternative.c
+++ b/avahi-common/alternative.c
@@ -49,15 +49,20 @@ static void drop_incomplete_utf8(char *c
}
char *avahi_alternative_host_name(const char *s) {
+ char label[AVAHI_LABEL_MAX], alternative[AVAHI_LABEL_MAX*4+1];
+ char *alt, *r, *ret;
const char *e;
- char *r;
+ size_t len;
assert(s);
if (!avahi_is_valid_host_name(s))
return NULL;
- if ((e = strrchr(s, '-'))) {
+ if (!avahi_unescape_label(&s, label, sizeof(label)))
+ return NULL;
+
+ if ((e = strrchr(label, '-'))) {
const char *p;
e++;
@@ -74,19 +79,18 @@ char *avahi_alternative_host_name(const
if (e) {
char *c, *m;
- size_t l;
int n;
n = atoi(e)+1;
if (!(m = avahi_strdup_printf("%i", n)))
return NULL;
- l = e-s-1;
+ len = e-label-1;
- if (l >= AVAHI_LABEL_MAX-1-strlen(m)-1)
- l = AVAHI_LABEL_MAX-1-strlen(m)-1;
+ if (len >= AVAHI_LABEL_MAX-1-strlen(m)-1)
+ len = AVAHI_LABEL_MAX-1-strlen(m)-1;
- if (!(c = avahi_strndup(s, l))) {
+ if (!(c = avahi_strndup(label, len))) {
avahi_free(m);
return NULL;
}
@@ -100,7 +104,7 @@ char *avahi_alternative_host_name(const
} else {
char *c;
- if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-2)))
+ if (!(c = avahi_strndup(label, AVAHI_LABEL_MAX-1-2)))
return NULL;
drop_incomplete_utf8(c);
@@ -109,6 +113,13 @@ char *avahi_alternative_host_name(const
avahi_free(c);
}
+ alt = alternative;
+ len = sizeof(alternative);
+ ret = avahi_escape_label(r, strlen(r), &alt, &len);
+
+ avahi_free(r);
+ r = avahi_strdup(ret);
+
assert(avahi_is_valid_host_name(r));
return r;
+204
View File
@@ -0,0 +1,204 @@
#!/bin/sh
_version_check() {
local bin="$1" pkg="$2" ver="$3"
# apk versions use _ where upstream uses - (e.g. 0.9_rc4 vs 0.9-rc4)
local upstream_ver
upstream_ver=$(echo "$ver" | tr '_' '-')
"$bin" -V 2>&1 | grep -F "$upstream_ver" || {
echo "FAIL: $bin -V did not print expected version '$upstream_ver'"
exit 1
}
}
_lib_check() {
local f="$1"
[ -e "$f" ] || { echo "FAIL: $f not found"; exit 1; }
}
# Test avahi-daemon startup with a minimal config.
# Works for both dbus and nodbus variants; dbus variant skips the start
# test when avahi-utils (which needs dbus) is not installed.
_daemon_start_test() {
local ver="$1"
_version_check avahi-daemon avahi-daemon "$ver"
# Config file from package
[ -f /etc/avahi/avahi-daemon.conf ] || {
echo "FAIL: /etc/avahi/avahi-daemon.conf not installed"
exit 1
}
grep -q "use-ipv4=yes" /etc/avahi/avahi-daemon.conf || {
echo "FAIL: use-ipv4=yes not found in avahi-daemon.conf"
exit 1
}
[ -d /etc/avahi/services ] || {
echo "FAIL: /etc/avahi/services directory not installed"
exit 1
}
# Try to start avahi-daemon with a minimal config and no privilege drop
mkdir -p /var/run/avahi-daemon /tmp/avahi-test
cat > /tmp/avahi-test/avahi-daemon.conf << 'EOF'
[server]
host-name=avahi-test
use-ipv4=yes
use-ipv6=no
check-response-ttl=no
use-iff-running=no
enable-dbus=no
[wide-area]
enable-wide-area=no
[publish]
publish-addresses=yes
publish-hinfo=no
publish-workstation=no
publish-domain=yes
disable-publishing=no
[reflector]
enable-reflector=no
[rlimits]
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=30
rlimit-stack=4194304
rlimit-nproc=3
EOF
avahi-daemon --no-drop-root --no-chroot \
--file=/tmp/avahi-test/avahi-daemon.conf \
-D 2>/tmp/avahi-test/daemon.log
# Wait for pid file
i=0
while [ $i -lt 10 ] && [ ! -f /var/run/avahi-daemon/pid ]; do
sleep 1
i=$((i + 1))
done
if [ -f /var/run/avahi-daemon/pid ]; then
echo "avahi-daemon started (pid $(cat /var/run/avahi-daemon/pid))"
# Verify socket exists
[ -e /var/run/avahi-daemon/socket ] && echo "socket present" || \
echo "NOTE: socket not present (may need network)"
# Stop the daemon
kill "$(cat /var/run/avahi-daemon/pid)" 2>/dev/null
i=0
while [ $i -lt 5 ] && [ -f /var/run/avahi-daemon/pid ]; do
sleep 1; i=$((i + 1))
done
echo "avahi-daemon stopped"
else
echo "NOTE: avahi-daemon did not start within 10s (may need network interface)"
echo "daemon log:"
cat /tmp/avahi-test/daemon.log 2>/dev/null
# Not a hard failure — network may not be available in all test envs
fi
rm -rf /tmp/avahi-test
}
_service_file_check() {
local f="$1" stype="$2" port="$3"
[ -f "$f" ] || { echo "FAIL: $f not found"; exit 1; }
# Validate it is XML and contains expected service attributes
grep -q "<service-group>" "$f" || { echo "FAIL: $f missing <service-group>"; exit 1; }
grep -q "<type>_${stype}._tcp</type>" "$f" || {
echo "FAIL: $f missing <type>_${stype}._tcp</type>"
exit 1
}
grep -q "<port>$port</port>" "$f" || {
echo "FAIL: $f missing <port>$port</port>"
exit 1
}
echo "$f: OK"
}
case "$1" in
libavahi-dbus-support)
_lib_check /usr/lib/libavahi-common.so.3
_lib_check /usr/lib/libavahi-core.so.7
# D-Bus policy file
[ -f /etc/dbus-1/system.d/avahi-dbus.conf ] || {
echo "FAIL: avahi D-Bus policy not installed"
exit 1
}
grep -q "avahi" /etc/dbus-1/system.d/avahi-dbus.conf || {
echo "FAIL: avahi-dbus.conf does not mention avahi"
exit 1
}
;;
libavahi-nodbus-support)
_lib_check /usr/lib/libavahi-common.so.3
_lib_check /usr/lib/libavahi-core.so.7
;;
libavahi-client)
_lib_check /usr/lib/libavahi-client.so.3
;;
avahi-dbus-daemon|avahi-nodbus-daemon)
_daemon_start_test "$2"
;;
avahi-autoipd)
_version_check avahi-autoipd avahi-autoipd "$2"
[ -x /usr/sbin/avahi-autoipd ] || { echo "FAIL: avahi-autoipd not executable"; exit 1; }
[ -x /etc/avahi/avahi-autoipd.action ] || {
echo "FAIL: avahi-autoipd.action script not installed"
exit 1
}
[ -f /lib/netifd/proto/autoip.sh ] || {
echo "FAIL: netifd autoip proto script not installed"
exit 1
}
;;
avahi-daemon-service-http)
_service_file_check /etc/avahi/services/http.service http 80
;;
avahi-daemon-service-ssh)
_service_file_check /etc/avahi/services/ssh.service ssh 22
;;
avahi-dnsconfd)
_version_check avahi-dnsconfd avahi-dnsconfd "$2"
[ -x /usr/sbin/avahi-dnsconfd ] || { echo "FAIL: avahi-dnsconfd not executable"; exit 1; }
[ -x /etc/avahi/avahi-dnsconfd.action ] || {
echo "FAIL: avahi-dnsconfd.action not installed"
exit 1
}
;;
avahi-utils)
# All four utilities must be present and print a help/usage line
for bin in avahi-browse avahi-publish avahi-resolve avahi-set-host-name; do
[ -x "/usr/bin/$bin" ] || { echo "FAIL: $bin not found"; exit 1; }
# --help exits non-zero on some versions; capture stderr+stdout
"$bin" --help 2>&1 | grep -qi "usage\|help\|option" || {
echo "FAIL: $bin --help produced no usage output"
exit 1
}
echo "$bin: OK"
done
# Verify avahi-browse can list service types (fails fast without daemon;
# the important thing is the binary runs and parses arguments)
avahi-browse --terminate --all 2>&1 | grep -qi "avahi\|failed\|error\|No.*daemon\|socket\|service" && \
echo "avahi-browse --terminate --all: ran" || \
echo "avahi-browse --terminate --all: no output (daemon not running)"
;;
esac