diff --git a/SOURCES/dnsmasq-2.76-CVE-2019-14834.patch b/SOURCES/dnsmasq-2.76-CVE-2019-14834.patch new file mode 100644 index 0000000..8ae891a --- /dev/null +++ b/SOURCES/dnsmasq-2.76-CVE-2019-14834.patch @@ -0,0 +1,46 @@ +From 69bc94779c2f035a9fffdb5327a54c3aeca73ed5 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Wed, 14 Aug 2019 20:44:50 +0100 +Subject: [PATCH] Fix memory leak in helper.c + +Thanks to Xu Mingjie for spotting this. +--- + src/helper.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/helper.c b/src/helper.c +index 33ba120..c392eec 100644 +--- a/src/helper.c ++++ b/src/helper.c +@@ -80,7 +80,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) + pid_t pid; + int i, pipefd[2]; + struct sigaction sigact; +- ++ unsigned char *alloc_buff = NULL; ++ + /* create the pipe through which the main program sends us commands, + then fork our process. */ + if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1) +@@ -186,11 +187,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) + struct script_data data; + char *p, *action_str, *hostname = NULL, *domain = NULL; + unsigned char *buf = (unsigned char *)daemon->namebuff; +- unsigned char *end, *extradata, *alloc_buff = NULL; ++ unsigned char *end, *extradata; + int is6, err = 0; + int pipeout[2]; + +- free(alloc_buff); ++ /* Free rarely-allocated memory from previous iteration. */ ++ if (alloc_buff) ++ { ++ free(alloc_buff); ++ alloc_buff = NULL; ++ } + + /* we read zero bytes when pipe closed: this is our signal to exit */ + if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1)) +-- +2.21.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1755610.patch b/SOURCES/dnsmasq-2.76-rh1755610.patch new file mode 100644 index 0000000..54526c8 --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1755610.patch @@ -0,0 +1,99 @@ +From 6ff6c5003120fbb609cb2e2739679fd4583731f6 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Wed, 19 Sep 2018 22:27:11 +0100 +Subject: [PATCH] Change behavior when RD bit unset in queries. + +Change anti cache-snooping behaviour with queries with the +recursion-desired bit unset. Instead to returning SERVFAIL, we +now always forward, and never answer from the cache. This +allows "dig +trace" command to work. + +(cherry picked from commit 4139298d287eb5c57f4aa53c459cb02fc5be2495) + +Restore ability to answer non-recursive requests + +Instead, check only local configured entries are answered without +rdbit set. All cached replies are still denied, but locally configured +names are available with both recursion and without it. + +Fixes commit 4139298d287eb5c57f4aa53c459cb02fc5be2495 unintended +behaviour. + +(cherry picked from commit 29ae3083981ea82f535f77ea54bbd538f1224a9e) +--- + src/rfc1035.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/rfc1035.c b/src/rfc1035.c +index 96acae9..ae2cc96 100644 +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1252,7 +1252,6 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now) + else + return daemon->max_ttl; + } +- + + /* return zero if we can't answer from cache, or packet size if we can */ + size_t answer_request(struct dns_header *header, char *limit, size_t qlen, +@@ -1271,12 +1270,15 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1; + struct mx_srv_record *rec; + size_t len; ++ int rd_bit; + // Make sure we do not underflow here too. + if (qlen > (limit - ((char *)header))) return 0; ++ rd_bit = (header->hb3 & HB3_RD); + ++ /* never answer queries with RD unset, to avoid cache snooping. */ + if (ntohs(header->ancount) != 0 || + ntohs(header->nscount) != 0 || +- ntohs(header->qdcount) == 0 || ++ ntohs(header->qdcount) == 0 || + OPCODE(header) != QUERY ) + return 0; + +@@ -1443,9 +1445,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + /* Don't use cache when DNSSEC data required, unless we know that + the zone is unsigned, which implies that we're doing + validation. */ +- if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || +- !do_bit || +- (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) ++ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || ++ (rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))) + { + do + { +@@ -1633,8 +1634,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + + /* If the client asked for DNSSEC don't use cached data. */ + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || +- !do_bit || +- (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) ++ (rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) )) + do + { + /* don't answer wildcard queries with data not from /etc/hosts +@@ -1718,7 +1718,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + { + if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) && + (qtype == T_CNAME || (crecp->flags & F_CONFIG)) && +- ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))) ++ ((crecp->flags & F_CONFIG) || ++ (rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))))) + { + if (!(crecp->flags & F_DNSSECOK)) + sec_data = 0; +@@ -1756,7 +1757,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, + } + } + +- if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && ++ if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && + cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR)) + { + ans = 1; +-- +2.21.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1757247.patch b/SOURCES/dnsmasq-2.76-rh1757247.patch new file mode 100644 index 0000000..1fa1081 --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1757247.patch @@ -0,0 +1,32 @@ +From 95b743d5b0e207ecbe92252757100641b5e13d35 Mon Sep 17 00:00:00 2001 +From: yiwenchen +Date: Wed, 14 Feb 2018 22:26:54 +0000 +Subject: [PATCH] Fix boundary for test introduced in + 3e3f1029c9ec6c63e430ff51063a6301d4b2262 + +This fixes breakage of DHCPv6 relay. + +(cherry picked from commit 499d8dde2b1a216eab9252ee500cc31b8c2b2974) +--- + src/rfc3315.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 1e85c5c..42c7a0e 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -216,9 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, + + for (opt = opts; opt; opt = opt6_next(opt, end)) + { +- if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) { ++ if (opt6_ptr(opt, 0) + opt6_len(opt) > end) + return 0; +- } ++ + int o = new_opt6(opt6_type(opt)); + if (opt6_type(opt) == OPTION6_RELAY_MSG) + { +-- +2.21.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1815080.patch b/SOURCES/dnsmasq-2.76-rh1815080.patch new file mode 100644 index 0000000..e83e5fe --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1815080.patch @@ -0,0 +1,160 @@ +From 63b84acdf5bd7971a7da3137a6aa609c71205625 Mon Sep 17 00:00:00 2001 +From: Hans Dedecker +Date: Tue, 27 Jun 2017 22:08:47 +0100 +Subject: [PATCH] Try other servers if first returns REFUSED when + --strict-order active. + +If a DNS server replies REFUSED for a given DNS query in strict order mode +no failover to the next DNS server is triggered as the failover logic only +covers non strict mode. +As a result the client will be returned the REFUSED reply without first +falling back to the secondary DNS server(s). + +Make failover support work as well for strict mode config in case REFUSED is +replied by deleting the strict order check and rely only on forwardall being +equal to 0 which is the case in non strict mode when a single server has been +contacted or when strict order mode has been configured. + +(cherry picked from commit 9396752c115b3ab733fa476b30da73237e12e7ba) + +Stop treating SERVFAIL as a successful response from upstream servers. + +This effectively reverts most of 51967f9807 ("SERVFAIL is an expected +error return, don't try all servers.") and 4ace25c5d6 ("Treat REFUSED (not +SERVFAIL) as an unsuccessful upstream response"). + +With the current behaviour, as soon as dnsmasq receives a SERVFAIL from an +upstream server, it stops trying to resolve the query and simply returns +SERVFAIL to the client. With this commit, dnsmasq will instead try to +query other upstream servers upon receiving a SERVFAIL response. + +According to RFC 1034 and 1035, the semantic of SERVFAIL is that of a +temporary error condition. Recursive resolvers are expected to encounter +network or resources issues from time to time, and will respond with +SERVFAIL in this case. Similarly, if a validating DNSSEC resolver [RFC +4033] encounters issues when checking signatures (unknown signing +algorithm, missing signatures, expired signatures because of a wrong +system clock, etc), it will respond with SERVFAIL. + +Note that all those behaviours are entirely different from a negative +response, which would provide a definite indication that the requested +name does not exist. In our case, if an upstream server responds with +SERVFAIL, another upstream server may well provide a positive answer for +the same query. + +Thus, this commit will increase robustness whenever some upstream servers +encounter temporary issues or are misconfigured. + +Quoting RFC 1034, Section 4.3.1. "Queries and responses": + + If recursive service is requested and available, the recursive response + to a query will be one of the following: + + - The answer to the query, possibly preface by one or more CNAME + RRs that specify aliases encountered on the way to an answer. + + - A name error indicating that the name does not exist. This + may include CNAME RRs that indicate that the original query + name was an alias for a name which does not exist. + + - A temporary error indication. + +Here is Section 5.2.3. of RFC 1034, "Temporary failures": + + In a less than perfect world, all resolvers will occasionally be unable + to resolve a particular request. This condition can be caused by a + resolver which becomes separated from the rest of the network due to a + link failure or gateway problem, or less often by coincident failure or + unavailability of all servers for a particular domain. + +And finally, RFC 1035 specifies RRCODE 2 for this usage, which is now more +widely known as SERVFAIL (RFC 1035, Section 4.1.1. "Header section format"): + + RCODE Response code - this 4 bit field is set as part of + responses. The values have the following + interpretation: + (...) + + 2 Server failure - The name server was + unable to process this query due to a + problem with the name server. + +For the DNSSEC-related usage of SERVFAIL, here is RFC 4033 +Section 5. "Scope of the DNSSEC Document Set and Last Hop Issues": + + A validating resolver can determine the following 4 states: + (...) + + Insecure: The validating resolver has a trust anchor, a chain of + trust, and, at some delegation point, signed proof of the + non-existence of a DS record. This indicates that subsequent + branches in the tree are provably insecure. A validating resolver + may have a local policy to mark parts of the domain space as + insecure. + + Bogus: The validating resolver has a trust anchor and a secure + delegation indicating that subsidiary data is signed, but the + response fails to validate for some reason: missing signatures, + expired signatures, signatures with unsupported algorithms, data + missing that the relevant NSEC RR says should be present, and so + forth. + (...) + + This specification only defines how security-aware name servers can + signal non-validating stub resolvers that data was found to be bogus + (using RCODE=2, "Server Failure"; see [RFC4035]). + +Notice the difference between a definite negative answer ("Insecure" +state), and an indefinite error condition ("Bogus" state). The second +type of error may be specific to a recursive resolver, for instance +because its system clock has been incorrectly set, or because it does not +implement newer cryptographic primitives. Another recursive resolver may +succeed for the same query. + +There are other similar situations in which the specified behaviour is +similar to the one implemented by this commit. + +For instance, RFC 2136 specifies the behaviour of a "requestor" that wants +to update a zone using the DNS UPDATE mechanism. The requestor tries to +contact all authoritative name servers for the zone, with the following +behaviour specified in RFC 2136, Section 4: + + 4.6. If a response is received whose RCODE is SERVFAIL or NOTIMP, or + if no response is received within an implementation dependent timeout + period, or if an ICMP error is received indicating that the server's + port is unreachable, then the requestor will delete the unusable + server from its internal name server list and try the next one, + repeating until the name server list is empty. If the requestor runs + out of servers to try, an appropriate error will be returned to the + requestor's caller. + +(cherry picked from commit 68f6312d4bae30b78daafcd6f51dc441b8685b1e) +--- + src/forward.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/forward.c b/src/forward.c +index 245c448..1bbb264 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -794,7 +794,6 @@ void reply_query(int fd, int family, time_t now) + /* Note: if we send extra options in the EDNS0 header, we can't recreate + the query from the reply. */ + if (RCODE(header) == REFUSED && +- !option_bool(OPT_ORDER) && + forward->forwardall == 0 && + !(forward->flags & FREC_HAS_EXTRADATA)) + /* for broken servers, attempt to send to another one. */ +@@ -859,7 +858,8 @@ void reply_query(int fd, int family, time_t now) + we get a good reply from another server. Kill it when we've + had replies from all to avoid filling the forwarding table when + everything is broken */ +- if (forward->forwardall == 0 || --forward->forwardall == 1 || RCODE(header) != REFUSED) ++ if (forward->forwardall == 0 || --forward->forwardall == 1 || ++ (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL)) + { + int check_rebind = 0, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; + +-- +2.21.1 + diff --git a/SOURCES/dnsmasq-2.79-fix-infitite-strict-mode-retries.patch b/SOURCES/dnsmasq-2.79-fix-infitite-strict-mode-retries.patch new file mode 100644 index 0000000..6a6d45b --- /dev/null +++ b/SOURCES/dnsmasq-2.79-fix-infitite-strict-mode-retries.patch @@ -0,0 +1,52 @@ +From eb79fee19724dcfde162892cfb4b9175a470308a Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Tue, 5 Dec 2017 22:37:29 +0000 +Subject: [PATCH] Fix infinite retries in strict-order mode. + + If all configured dns servers return refused in + response to a query; dnsmasq will end up in an infinite loop + retransmitting the dns query resulting into high CPU load. + Problem is caused by the dns refuse retransmission logic which does + not check for the end of a dns server list iteration in strict mode. + Having one configured dns server returning a refused reply easily + triggers this problem in strict order mode. This was introduced in + 9396752c115b3ab733fa476b30da73237e12e7ba + + Thanks to Hans Dedecker for spotting this + and the initial patch. + +(cherry picked from commit ef3d137a646fa8309e1ff5184e3e145eef40cc4d) +--- + src/forward.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/forward.c b/src/forward.c +index 255d6c0..e61cd50 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -804,10 +804,20 @@ void reply_query(int fd, int family, time_t now) + unsigned char *pheader; + size_t plen; + int is_sign; +- ++ ++ /* In strict order mode, there must be a server later in the chain ++ left to send to, otherwise without the forwardall mechanism, ++ code further on will cycle around the list forwever if they ++ all return REFUSED. Note that server is always non-NULL before ++ this executes. */ ++ if (option_bool(OPT_ORDER)) ++ for (server = forward->sentto->next; server; server = server->next) ++ if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR | SERV_LOOP))) ++ break; ++ + /* recreate query from reply */ + pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign, NULL); +- if (!is_sign) ++ if (!is_sign && server) + { + header->ancount = htons(0); + header->nscount = htons(0); +-- +2.26.2 + diff --git a/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec index 4b22ec5..84f6dc7 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -13,7 +13,7 @@ Name: dnsmasq Version: 2.76 -Release: 10%{?extraversion}%{?dist}.1 +Release: 16%{?extraversion}%{?dist} Summary: A lightweight DHCP/caching DNS server Group: System Environment/Daemons @@ -67,6 +67,17 @@ Patch27: dnsmasq-2.76-rh1721668-3.patch Patch28: dnsmasq-2.76-rh1721668-4.patch # commit 60ac10d8d86e6f95ab0f06abe6c42596adcedcb8 Patch29: dnsmasq-2.76-rh1752569.patch +# commit 69bc94779c2f035a9fffdb5327a54c3aeca73ed5 +Patch30: dnsmasq-2.76-CVE-2019-14834.patch +# commit 499d8dde2b1a216eab9252ee500cc31b8c2b2974 +Patch31: dnsmasq-2.76-rh1757247.patch +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=68f6312d4bae30b78daafcd6f51dc441b8685b1e +Patch32: dnsmasq-2.76-rh1815080.patch +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=4139298d287eb5c57f4aa53c459cb02fc5be2495 +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=29ae3083981ea82f535f77ea54bbd538f1224a9e +Patch33: dnsmasq-2.76-rh1755610.patch +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=ef3d137a646fa8309e1ff5184e3e145eef40cc4d +Patch34: dnsmasq-2.79-fix-infitite-strict-mode-retries.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -131,6 +142,11 @@ query/remove a DHCP server's leases. %patch27 -p1 -b .rh1721668-3 %patch28 -p1 -b .rh1721668-4 %patch29 -p1 -b .rh1752569 +%patch30 -p1 -b .CVE-2019-14834 +%patch31 -p1 -b .rh1757247 +%patch32 -p1 -b .rh1815080 +%patch33 -p1 -b .rh1755610 +%patch34 -p1 -b .rh1755610-strict-mode # use /var/lib/dnsmasq instead of /var/lib/misc for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do @@ -217,7 +233,22 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man1/dhcp_* %changelog -* Mon Sep 30 2019 Petr Menšík - 2.76-10.1 +* Thu Jul 02 2020 Petr Menšík - 2.76-16 +- Fix strict-mode retries on REFUSED (#1755610) + +* Tue Apr 21 2020 Petr Menšík - 2.76-15 +- Forward non-recursive queries to upstream, but serve local names (#1755610) + +* Thu Apr 09 2020 Petr Menšík - 2.76-14 +- Stop treating SERVFAIL as successful response (#1815080) + +* Tue Mar 03 2020 Petr Menšík - 2.76-13 +- Do not ignore DHCPv6 relay messages (#1757247) + +* Mon Mar 02 2020 Petr Menšík - 2.76-12 +- Fix memory leak in create_helper (#1795369) + +* Mon Sep 30 2019 Petr Menšík - 2.76-11 - Send dhcp_release even for addresses not on local network (#1752569) * Wed Jul 03 2019 Petr Menšík - 2.76-10