From 8b2e362651ca7f921ae9cd46a851f31eb2a7c903 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 29 Oct 2020 18:58:04 +0100 Subject: [PATCH 1/6] man: remove misplaced comma --- man/udev_device_get_syspath.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/udev_device_get_syspath.xml b/man/udev_device_get_syspath.xml index 0deb1d0d2c..74de224b56 100644 --- a/man/udev_device_get_syspath.xml +++ b/man/udev_device_get_syspath.xml @@ -173,7 +173,7 @@ udev_enumerate_new3, udev_monitor_new_from_netlink3, udev_list_entry3, - systemd1, + systemd1 From a63a1252b501f6c8b5a011825372977710e88e72 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Nov 2020 18:06:47 +0100 Subject: [PATCH 2/6] resolved: check return value of memdup() correctly for OOM --- src/resolve/resolved-dns-rr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c index 9ca7ad96fd..2db7ec4a0a 100644 --- a/src/resolve/resolved-dns-rr.c +++ b/src/resolve/resolved-dns-rr.c @@ -1650,7 +1650,7 @@ DnsResourceRecord *dns_resource_record_copy(DnsResourceRecord *rr) { return NULL; copy->nsec3.salt_size = rr->nsec3.salt_size; copy->nsec3.next_hashed_name = memdup(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size); - if (!copy->nsec3.next_hashed_name_size) + if (!copy->nsec3.next_hashed_name) return NULL; copy->nsec3.next_hashed_name_size = rr->nsec3.next_hashed_name_size; copy->nsec3.types = bitmap_copy(rr->nsec3.types); From 398c611833584632c6977e2f89746403108637c7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Nov 2020 18:31:03 +0100 Subject: [PATCH 3/6] resolved: put size limit in DnsAnswer size to UINT16_MAX The three answer sections can only carry up to UINT16_MAX entries, hence put a hard upper limit on how far DnsAnswer can grow. The three count fields in the DNS packet header are 16 bit only, hence the limit. If code actually tries to add more than 64K RRs it will get ENOSPC with this new checking. And similar to DnsQuestion. --- src/resolve/resolved-dns-answer.c | 7 +++++++ src/resolve/resolved-dns-question.c | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index d6fba7ead0..74d185fbd6 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -11,6 +11,9 @@ DnsAnswer *dns_answer_new(size_t n) { DnsAnswer *a; + if (n > UINT16_MAX) /* We can only place 64K RRs in an answer at max */ + n = UINT16_MAX; + a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n); if (!a) return NULL; @@ -624,12 +627,16 @@ int dns_answer_reserve(DnsAnswer **a, size_t n_free) { return -EBUSY; ns = (*a)->n_rrs + n_free; + if (ns > UINT16_MAX) /* Maximum number of RRs we can stick into a DNS packet section */ + ns = UINT16_MAX; if ((*a)->n_allocated >= ns) return 0; /* Allocate more than we need */ ns *= 2; + if (ns > UINT16_MAX) + ns = UINT16_MAX; n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns); if (!n) diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c index 62833efa0e..809965a845 100644 --- a/src/resolve/resolved-dns-question.c +++ b/src/resolve/resolved-dns-question.c @@ -8,7 +8,8 @@ DnsQuestion *dns_question_new(size_t n) { DnsQuestion *q; - assert(n > 0); + if (n > UINT16_MAX) /* We can only place 64K key in an question section at max */ + n = UINT16_MAX; q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n); if (!q) From 014e8cc131109e2a1995fcfe0550a77e6a9b42b2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 28 Oct 2020 14:54:12 +0100 Subject: [PATCH 4/6] resolved: fix dumping of DnsAnswer objects --- src/resolve/resolved-dns-answer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index 74d185fbd6..823c138b34 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -713,7 +713,7 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f) { fputs("\t;", f); if (ifindex != 0) - printf(" ifindex=%i", ifindex); + fprintf(f, " ifindex=%i", ifindex); if (flags & DNS_ANSWER_AUTHENTICATED) fputs(" authenticated", f); if (flags & DNS_ANSWER_CACHEABLE) From de4a0138e7a1836649928989dbacb59c5c2614f7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 28 Oct 2020 15:12:32 +0100 Subject: [PATCH 5/6] resolved: drop unused family argument from manager_routable() --- src/resolve/resolved-dns-scope.c | 8 ++++++-- src/resolve/resolved-manager.c | 6 +++--- src/resolve/resolved-manager.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 2ad4544002..9bf52d62e5 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -1156,12 +1156,16 @@ bool dns_scope_name_wants_search_domain(DnsScope *s, const char *name) { bool dns_scope_network_good(DnsScope *s) { /* Checks whether the network is in good state for lookups on this scope. For mDNS/LLMNR/Classic DNS scopes * bound to links this is easy, as they don't even exist if the link isn't in a suitable state. For the global - * DNS scope we check whether there are any links that are up and have an address. */ + * DNS scope we check whether there are any links that are up and have an address. + * + * Note that Linux routing is complex and even systems that superficially have no IPv4 address might + * be able to route IPv4 (and similar for IPv6), hence let's make a check here independent of address + * family. */ if (s->link) return true; - return manager_routable(s->manager, AF_UNSPEC); + return manager_routable(s->manager); } int dns_scope_ifindex(DnsScope *s) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index c197108810..bb333e22eb 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -1418,15 +1418,15 @@ void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResource m->n_dnssec_verdict[verdict]++; } -bool manager_routable(Manager *m, int family) { +bool manager_routable(Manager *m) { Link *l; assert(m); - /* Returns true if the host has at least one interface with a routable address of the specified type */ + /* Returns true if the host has at least one interface with a routable address (regardless if IPv4 or IPv6) */ HASHMAP_FOREACH(l, m->links) - if (link_relevant(l, family, false)) + if (link_relevant(l, AF_UNSPEC, false)) return true; return false; diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index c30052195a..a2dd9ae1ff 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -185,7 +185,7 @@ DnsOverTlsMode manager_get_dns_over_tls_mode(Manager *m); void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResourceKey *key); -bool manager_routable(Manager *m, int family); +bool manager_routable(Manager *m); void manager_flush_caches(Manager *m); void manager_reset_server_features(Manager *m); From 2f4c2db20ae02d750a6995e0afbff7231cd3a6b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Nov 2020 20:34:21 +0100 Subject: [PATCH 6/6] resolved: handle RRs where we don't have a signer If we encounter an RR that has no matching signature, then we don't know whether it was expanded from a wildcard or not. We need to accept that and not make the NSEC test fail, just skip over the RR. --- src/resolve/resolved-dns-dnssec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c index 5a4f5c58b6..5a01d49dee 100644 --- a/src/resolve/resolved-dns-dnssec.c +++ b/src/resolve/resolved-dns-dnssec.c @@ -1813,6 +1813,8 @@ int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *r /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */ r = dns_resource_record_is_synthetic(rr); + if (r == -ENODATA) /* No signing RR known. */ + continue; if (r < 0) return r; if (r > 0)