Sync from SUSE:ALP:Source:Standard:1.0 avahi revision 63133e4596f227d4b0d82a5246ef7119

This commit is contained in:
Adrian Schröter 2024-09-05 15:33:31 +02:00
parent afc3ad3bef
commit 5f57cbe813
5 changed files with 292 additions and 0 deletions

View File

@ -0,0 +1,46 @@
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(-)
diff --git a/avahi-core/rr.c b/avahi-core/rr.c
index 2bb8924..9c04ebb 100644
--- 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"
@@ -689,11 +690,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;
}
}
--
2.44.0

View File

@ -0,0 +1,71 @@
From 894f085f402e023a98cbb6f5a3d117bd88d93b09 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(-)
diff --git a/avahi-core/server.c b/avahi-core/server.c
index c32637a..f6a21bb 100644
--- 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(AvahiServer *s, const char *host_name) {
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);
+
+ 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, hn) && s->state != AVAHI_SERVER_COLLISION) {
- avahi_free(hn);
+ 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);
--
2.44.0

View File

@ -0,0 +1,159 @@
From 93b14365c1c1e04efd1a890e8caa01a2a514bfd8 Mon Sep 17 00:00:00 2001
From: Evgeny Vereshchagin <evvers@ya.ru>
Date: Sun, 12 Nov 2023 01:16:58 +0000
Subject: [PATCH] core: no longer supply bogus services to callbacks
It was technically a DOS allowing packets with service names like
"bogus.service.local" to bring down `avahi-browse -a`. In practice
it was usually triggered by misconfigured smart devices but it isn't
that hard to forge packets like that and send them deliberately.
The tests are added to make sure invalid service names are rejected and
valid service names keep working. The fuzz target is updated to make
sure that avahi_service_name_split always supplies valid arguments to
avahi_service_name_join. avahi now logs what exactly it fails to split
```
avahi-daemon[176]: Failed to split service name '0.1.9.1.8.8.e.f.f.f.f.a.a.1.4.7.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa'
avahi-daemon[176]: Failed to split service name 'bogus\032.\032\209\129\208\181\209\128\208\178\208\184\209\129.local'
avahi-daemon[176]: Failed to split service name '255.20.254.169.in-addr.arpa'
avahi-daemon[176]: Failed to split service name 'bogus\032.\032\209\129\208\181\209\128\208\178\208\184\209\129.local'
avahi-daemon[176]: Failed to split service name '33.93.168.192.in-addr.arpa'
```
when --debug is passed to it (which makes that part consistent with the
other places where weird packets are rejected).
Closes https://github.com/lathiat/avahi/issues/212
---
.github/workflows/smoke-tests.sh | 2 ++
avahi-common/domain-test.c | 36 ++++++++++++++++++++++++++++++++
avahi-common/domain.c | 14 +++++++++++++
avahi-core/browse-service-type.c | 2 +-
avahi-core/browse-service.c | 2 +-
fuzz/fuzz-packet.c | 18 ++++++++--------
6 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/avahi-common/domain-test.c b/avahi-common/domain-test.c
index 7a662da..9679e98 100644
--- a/avahi-common/domain-test.c
+++ b/avahi-common/domain-test.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include "domain.h"
+#include "error.h"
#include "malloc.h"
int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
@@ -34,6 +35,7 @@ int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
const char *p;
size_t size;
char name[64], type[AVAHI_DOMAIN_NAME_MAX], domain[AVAHI_DOMAIN_NAME_MAX];
+ int res;
printf("%s\n", s = avahi_normalize_name_strdup("foo.foo\\046."));
avahi_free(s);
@@ -132,5 +134,39 @@ int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
assert(!avahi_is_valid_fqdn("::1"));
assert(!avahi_is_valid_fqdn(".192.168.50.1."));
+ res = avahi_service_name_split("test._ssh._tcp.local", name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+ assert(res >= 0);
+ assert(strcmp(name, "test") == 0);
+ assert(strcmp(type, "_ssh._tcp") == 0);
+ assert(strcmp(domain, "local") == 0);
+
+ res = avahi_service_name_split("test._hop._sub._ssh._tcp.local", name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+ assert(res >= 0);
+ assert(strcmp(name, "test") == 0);
+ assert(strcmp(type, "_hop._sub._ssh._tcp") == 0);
+ assert(strcmp(domain, "local") == 0);
+
+ res = avahi_service_name_split("_qotd._udp.hey.local", NULL, 0, type, sizeof(type), domain, sizeof(domain));
+ assert(res >= 0);
+ assert(strcmp(type, "_qotd._udp") == 0);
+ assert(strcmp(domain, "hey.local") == 0);
+
+ res = avahi_service_name_split("_wat._sub._qotd._udp.hey.local", NULL, 0, type, sizeof(type), domain, sizeof(domain));
+ assert(res >= 0);
+ assert(strcmp(type, "_wat._sub._qotd._udp") == 0);
+ assert(strcmp(domain, "hey.local") == 0);
+
+ res = avahi_service_name_split("wat.bogus.service.local", name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+ assert(res == AVAHI_ERR_INVALID_SERVICE_TYPE);
+
+ res = avahi_service_name_split("bogus.service.local", NULL, 0, type, sizeof(type), domain, sizeof(domain));
+ assert(res == AVAHI_ERR_INVALID_SERVICE_TYPE);
+
+ res = avahi_service_name_split("", name, sizeof(name), type, sizeof(type), domain, sizeof(domain));
+ assert(res == AVAHI_ERR_INVALID_SERVICE_NAME);
+
+ res = avahi_service_name_split("", NULL, 0, type, sizeof(type), domain, sizeof(domain));
+ assert(res == AVAHI_ERR_INVALID_SERVICE_TYPE);
+
return 0;
}
diff --git a/avahi-common/domain.c b/avahi-common/domain.c
index c7af116..9e93018 100644
--- a/avahi-common/domain.c
+++ b/avahi-common/domain.c
@@ -501,6 +501,7 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char *
DOMAIN
} state;
int type_empty = 1, domain_empty = 1;
+ char *oname, *otype, *odomain;
assert(p);
assert(type);
@@ -508,6 +509,10 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char *
assert(domain);
assert(domain_size > 0);
+ oname = name;
+ otype = type;
+ odomain = domain;
+
if (name) {
assert(name_size > 0);
*name = 0;
@@ -570,6 +575,15 @@ int avahi_service_name_split(const char *p, char *name, size_t name_size, char *
}
}
+ if ((oname && !avahi_is_valid_service_name(oname)))
+ return AVAHI_ERR_INVALID_SERVICE_NAME;
+
+ if (!avahi_is_valid_service_type_generic(otype))
+ return AVAHI_ERR_INVALID_SERVICE_TYPE;
+
+ if (!avahi_is_valid_domain_name(odomain))
+ return AVAHI_ERR_INVALID_DOMAIN_NAME;
+
return 0;
}
diff --git a/avahi-core/browse-service-type.c b/avahi-core/browse-service-type.c
index b1fc7af..f0d6938 100644
--- a/avahi-core/browse-service-type.c
+++ b/avahi-core/browse-service-type.c
@@ -65,7 +65,7 @@ static void record_browser_callback(
assert(record->key->type == AVAHI_DNS_TYPE_PTR);
if (avahi_service_name_split(record->data.ptr.name, NULL, 0, type, sizeof(type), domain, sizeof(domain)) < 0) {
- avahi_log_warn("Invalid service type '%s'", record->key->name);
+ avahi_log_debug("Failed to split service name '%s'", record->data.ptr.name);
return;
}
diff --git a/avahi-core/browse-service.c b/avahi-core/browse-service.c
index 63e0275..e924bae 100644
--- a/avahi-core/browse-service.c
+++ b/avahi-core/browse-service.c
@@ -69,7 +69,7 @@ static void record_browser_callback(
flags |= AVAHI_LOOKUP_RESULT_LOCAL;
if (avahi_service_name_split(record->data.ptr.name, service, sizeof(service), type, sizeof(type), domain, sizeof(domain)) < 0) {
- avahi_log_warn("Failed to split '%s'", record->key->name);
+ avahi_log_debug("Failed to split service name '%s'", record->data.ptr.name);
return;
}

View File

@ -1,3 +1,13 @@
-------------------------------------------------------------------
Mon Aug 5 20:01:31 UTC 2024 - Michael Gorse <mgorse@suse.com>
- Add avahi-CVE-2023-38471.patch: Extract host name using
avahi_unescape_label (bsc#1216594, CVE-2023-38471).
- Add avahi-CVE-2023-38469.patch: Reject overly long TXT resource
records (bsc#1216598, CVE-2023-38469).
- Add avahi-filter-bogus-services.patch: no longer supply bogus
services to callbacks (bsc#1226586).
-------------------------------------------------------------------
Thu Nov 30 05:23:33 UTC 2023 - Alynx Zhou <alynx.zhou@suse.com>

View File

@ -107,6 +107,12 @@ Patch31: avahi-CVE-2023-38473.patch
Patch32: avahi-CVE-2023-38470.patch
# PATCH-FIX-UPSTREAM avahi-CVE-2023-38472.patch bsc#1216853 alynx.zhou@suse.com -- Fix reachable assertion in avahi_rdata_parse
Patch33: avahi-CVE-2023-38472.patch
# PATCH-FIX-UPSTREAM avahi-CVE-2023-38469.patch bsc#1216598 xwang@suse.com -- Reject overly long TXT resource records
Patch34: avahi-CVE-2023-38469.patch
# PATCH-FIX-UPSTREAM avahi-CVE-2023-38471.patch bsc#1216594 xwang@suse.com -- Extract host name using avahi_unescape_label
Patch35: avahi-CVE-2023-38471.patch
# PATCH-FIX-UPSTREAM avahi-filter-bogus-services.patch bsc#1226586 mgorse@suse.com -- no longer supply bogus services to callbacks.
Patch36: avahi-filter-bogus-services.patch
BuildRequires: fdupes
BuildRequires: gcc-c++
BuildRequires: gdbm-devel