From d7059bf21e26ab3c5f50ae4d4eb02746f382f97f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 20 2020 14:01:01 +0000 Subject: import dnsmasq-2.76-14.el7 --- 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-rh1721668-1.patch b/SOURCES/dnsmasq-2.76-rh1721668-1.patch new file mode 100644 index 0000000..2546301 --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1721668-1.patch @@ -0,0 +1,52 @@ +From cae343c1f3bea9d1ca2e71d3709d3f02b799f94d Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Thu, 4 Jul 2019 20:28:08 +0200 +Subject: [PATCH 1/5] Log listening on new interfaces + +Log in debug mode listening on interfaces. They can be dynamically +found, include interface number, since it is checked on TCP connections. +Print also addresses found on them. +--- + src/network.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/network.c b/src/network.c +index d75f560..fd90288 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -662,6 +662,13 @@ int enumerate_interfaces(int reset) + else + { + *up = l->next; ++ if (l->iface->done) ++ { ++ iface = l->iface; ++ (void)prettyprint_addr(&iface->addr, daemon->addrbuff); ++ my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"), ++ iface->name, iface->index, daemon->addrbuff); ++ } + + /* In case it ever returns */ + l->iface->done = 0; +@@ -978,6 +985,9 @@ void create_bound_listeners(int dienow) + new->next = daemon->listeners; + daemon->listeners = new; + iface->done = 1; ++ (void)prettyprint_addr(&iface->addr, daemon->addrbuff); ++ my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"), ++ iface->name, iface->index, daemon->addrbuff); + } + + /* Check for --listen-address options that haven't been used because there's +@@ -997,6 +1007,8 @@ void create_bound_listeners(int dienow) + { + new->next = daemon->listeners; + daemon->listeners = new; ++ (void)prettyprint_addr(&if_tmp->addr, daemon->addrbuff); ++ my_syslog(LOG_DEBUG, _("listening on %s"), daemon->addrbuff); + } + } + +-- +2.20.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1721668-2.patch b/SOURCES/dnsmasq-2.76-rh1721668-2.patch new file mode 100644 index 0000000..13a3311 --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1721668-2.patch @@ -0,0 +1,48 @@ +From 7e3250d52921b5f75bdbe0b794514bb78a209969 Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Wed, 3 Jul 2019 17:02:16 +0200 +Subject: [PATCH 2/5] Compare address and interface index for allowed interface + +If interface is recreated with the same address but different index, it +would not change any other parameter. + +Test also address family on incoming TCP queries. +--- + src/dnsmasq.c | 3 ++- + src/network.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index f3d2671..7812be8 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -1614,7 +1614,8 @@ static void check_dns_listeners(time_t now) + #endif + + for (iface = daemon->interfaces; iface; iface = iface->next) +- if (iface->index == if_index) ++ if (iface->index == if_index && ++ iface->addr.sa.sa_family == tcp_addr.sa.sa_family) + break; + + if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name)) +diff --git a/src/network.c b/src/network.c +index fd90288..f247811 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -404,10 +404,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label, + /* check whether the interface IP has been added already + we call this routine multiple times. */ + for (iface = daemon->interfaces; iface; iface = iface->next) +- if (sockaddr_isequal(&iface->addr, addr)) ++ if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index) + { + iface->dad = !!(iface_flags & IFACE_TENTATIVE); + iface->found = 1; /* for garbage collection */ ++ iface->netmask = netmask; + return 1; + } + +-- +2.20.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1721668-3.patch b/SOURCES/dnsmasq-2.76-rh1721668-3.patch new file mode 100644 index 0000000..cdb690d --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1721668-3.patch @@ -0,0 +1,74 @@ +From 527029312cbe37c0285240943ad02352d64d403d Mon Sep 17 00:00:00 2001 +From: Petr Mensik +Date: Tue, 9 Jul 2019 14:05:59 +0200 +Subject: [PATCH 3/5] Cleanup interfaces no longer available + +Clean addresses and interfaces not found after enumerate. Free unused +records to speed up checking active interfaces and reduce used memory. +--- + src/network.c | 32 ++++++++++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +diff --git a/src/network.c b/src/network.c +index f247811..d6d4b01 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -553,7 +553,30 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label, + + return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0); + } +- ++ ++/* ++ * Clean old interfaces no longer found. ++ */ ++static void clean_interfaces() ++{ ++ struct irec *iface; ++ struct irec **up = &daemon->interfaces; ++ ++ for (iface = *up; iface; iface = *up) ++ { ++ if (!iface->found && !iface->done) ++ { ++ *up = iface->next; ++ free(iface->name); ++ free(iface); ++ } ++ else ++ { ++ up = &iface->next; ++ } ++ } ++} ++ + int enumerate_interfaces(int reset) + { + static struct addrlist *spare = NULL; +@@ -653,6 +676,7 @@ int enumerate_interfaces(int reset) + in OPT_CLEVERBIND mode, that at listener will just disappear after + a call to enumerate_interfaces, this is checked OK on all calls. */ + struct listener *l, *tmp, **up; ++ int freed = 0; + + for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp) + { +@@ -682,10 +706,14 @@ int enumerate_interfaces(int reset) + close(l->tftpfd); + + free(l); ++ freed = 1; + } + } ++ ++ if (freed) ++ clean_interfaces(); + } +- ++ + errno = errsave; + spare = param.spare; + +-- +2.20.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1721668-4.patch b/SOURCES/dnsmasq-2.76-rh1721668-4.patch new file mode 100644 index 0000000..78aecfe --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1721668-4.patch @@ -0,0 +1,188 @@ +From 11ab42e63f9089c4c14a391f30175d4c2d071e99 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Mon, 15 Jul 2019 17:13:12 +0200 +Subject: [PATCH 4/5] Handle listening on duplicate addresses + +Save listening address into listener. Use it to find existing listeners +before creating new one. If it exist, increase just used counter. +Release only listeners not already used. + +Duplicates family in listener. +--- + src/dnsmasq.h | 3 +- + src/network.c | 115 ++++++++++++++++++++++++++++++++++++-------------- + 2 files changed, 85 insertions(+), 33 deletions(-) + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 89d138a..3b3f6ef 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -526,7 +526,8 @@ struct irec { + }; + + struct listener { +- int fd, tcpfd, tftpfd, family; ++ int fd, tcpfd, tftpfd, family, used; ++ union mysockaddr addr; + struct irec *iface; /* only sometimes valid for non-wildcard */ + struct listener *next; + }; +diff --git a/src/network.c b/src/network.c +index d6d4b01..4bbd810 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -577,6 +577,56 @@ static void clean_interfaces() + } + } + ++/** Release listener if no other interface needs it. ++ * ++ * @return 1 if released, 0 if still required ++ */ ++static int release_listener(struct listener *l) ++{ ++ if (l->used > 1) ++ { ++ struct irec *iface; ++ for (iface = daemon->interfaces; iface; iface = iface->next) ++ if (iface->done && sockaddr_isequal(&l->addr, &iface->addr)) ++ { ++ if (iface->found) ++ { ++ /* update listener to point to active interface instead */ ++ if (!l->iface->found) ++ l->iface = iface; ++ } ++ else ++ { ++ l->used--; ++ iface->done = 0; ++ } ++ } ++ ++ /* Someone is still using this listener, skip its deletion */ ++ if (l->used > 0) ++ return 0; ++ } ++ ++ if (l->iface->done) ++ { ++ (void)prettyprint_addr(&l->iface->addr, daemon->addrbuff); ++ my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"), ++ l->iface->name, l->iface->index, daemon->addrbuff); ++ /* In case it ever returns */ ++ l->iface->done = 0; ++ } ++ ++ if (l->fd != -1) ++ close(l->fd); ++ if (l->tcpfd != -1) ++ close(l->tcpfd); ++ if (l->tftpfd != -1) ++ close(l->tftpfd); ++ ++ free(l); ++ return 1; ++} ++ + int enumerate_interfaces(int reset) + { + static struct addrlist *spare = NULL; +@@ -684,29 +734,10 @@ int enumerate_interfaces(int reset) + + if (!l->iface || l->iface->found) + up = &l->next; +- else ++ else if (release_listener(l)) + { +- *up = l->next; +- if (l->iface->done) +- { +- iface = l->iface; +- (void)prettyprint_addr(&iface->addr, daemon->addrbuff); +- my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s"), +- iface->name, iface->index, daemon->addrbuff); +- } +- +- /* In case it ever returns */ +- l->iface->done = 0; +- +- if (l->fd != -1) +- close(l->fd); +- if (l->tcpfd != -1) +- close(l->tcpfd); +- if (l->tftpfd != -1) +- close(l->tftpfd); +- +- free(l); +- freed = 1; ++ *up = tmp; ++ freed = 1; + } + } + +@@ -959,7 +990,9 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in + l->family = addr->sa.sa_family; + l->fd = fd; + l->tcpfd = tcpfd; +- l->tftpfd = tftpfd; ++ l->tftpfd = tftpfd; ++ l->addr = *addr; ++ l->used = 1; + l->iface = NULL; + } + +@@ -1000,23 +1033,41 @@ void create_wildcard_listeners(void) + daemon->listeners = l; + } + ++static struct listener *find_listener(union mysockaddr *addr) ++{ ++ struct listener *l; ++ for (l = daemon->listeners; l; l = l->next) ++ if (sockaddr_isequal(&l->addr, addr)) ++ return l; ++ return NULL; ++} ++ + void create_bound_listeners(int dienow) + { + struct listener *new; + struct irec *iface; + struct iname *if_tmp; ++ struct listener *existing; + + for (iface = daemon->interfaces; iface; iface = iface->next) +- if (!iface->done && !iface->dad && iface->found && +- (new = create_listeners(&iface->addr, iface->tftp_ok, dienow))) ++ if (!iface->done && !iface->dad && iface->found) + { +- new->iface = iface; +- new->next = daemon->listeners; +- daemon->listeners = new; +- iface->done = 1; +- (void)prettyprint_addr(&iface->addr, daemon->addrbuff); +- my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"), +- iface->name, iface->index, daemon->addrbuff); ++ existing = find_listener(&iface->addr); ++ if (existing) ++ { ++ iface->done = 1; ++ existing->used++; /* increase usage counter */ ++ } ++ else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow))) ++ { ++ new->iface = iface; ++ new->next = daemon->listeners; ++ daemon->listeners = new; ++ iface->done = 1; ++ (void)prettyprint_addr(&iface->addr, daemon->addrbuff); ++ my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s"), ++ iface->name, iface->index, daemon->addrbuff); ++ } + } + + /* Check for --listen-address options that haven't been used because there's +-- +2.20.1 + diff --git a/SOURCES/dnsmasq-2.76-rh1752569.patch b/SOURCES/dnsmasq-2.76-rh1752569.patch new file mode 100644 index 0000000..b46fcd3 --- /dev/null +++ b/SOURCES/dnsmasq-2.76-rh1752569.patch @@ -0,0 +1,75 @@ +From 3d27384fc5f2a437b7bce128c8ba62e8d6e12df7 Mon Sep 17 00:00:00 2001 +From: Brian Haley +Date: Wed, 28 Aug 2019 16:13:23 -0400 +Subject: [PATCH] Change dhcp_release to use default address when no IP subnet + matches + +Currently, dhcp_release will only send a 'fake' release +when the address given is in the same subnet as an IP +on the interface that was given. + +This doesn't work in an environment where dnsmasq is +managing leases for remote subnets via a DHCP relay, as +running dhcp_release locally will just cause it to +silently exit without doing anything, leaving the lease +in the database. + +Change it to use the default IP on the interface, as the +dnsmasq source code at src/dhcp.c does, if no matching subnet +IP is found, as a fall-back. This fixes an issue we are +seeing in certain Openstack deployments where we are using +dnsmasq to provision baremetal systems in a datacenter. + +While using Dbus might have seemed like an obvious solution, +because of our extensive use of network namespaces (which +Dbus doesn't support), this seemed like a better solution +than creating system.d policy files for each dnsmasq we +might spawn and using --enable-dbus=$id in order to isolate +messages to specific dnsmasq instances. + +Signed-off-by: Brian Haley +(cherry picked from commit d9f882bea2806799bf3d1f73937f5e72d0bfc650) +--- + contrib/lease-tools/dhcp_release.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/contrib/lease-tools/dhcp_release.c b/contrib/lease-tools/dhcp_release.c +index a51f04b..1dd8d32 100644 +--- a/contrib/lease-tools/dhcp_release.c ++++ b/contrib/lease-tools/dhcp_release.c +@@ -178,7 +178,7 @@ static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask) + return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr); + } + +-static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index) ++static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index, int ifrfd, struct ifreq *ifr) + { + struct sockaddr_nl addr; + struct nlmsghdr *h; +@@ -218,7 +218,13 @@ static struct in_addr find_interface(struct in_addr client, int fd, unsigned int + + for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) + if (h->nlmsg_type == NLMSG_DONE) +- exit(0); ++ { ++ /* No match found, return first address as src/dhcp.c code does */ ++ ifr->ifr_addr.sa_family = AF_INET; ++ if (ioctl(ifrfd, SIOCGIFADDR, ifr) != -1) ++ return ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; ++ exit(0); ++ } + else if (h->nlmsg_type == RTM_NEWADDR) + { + struct ifaddrmsg *ifa = NLMSG_DATA(h); +@@ -284,7 +290,7 @@ int main(int argc, char **argv) + } + + lease.s_addr = inet_addr(argv[2]); +- server = find_interface(lease, nl, if_nametoindex(argv[1])); ++ server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr); + + memset(&packet, 0, sizeof(packet)); + +-- +2.20.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/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec index b715e18..3283699 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -13,7 +13,7 @@ Name: dnsmasq Version: 2.76 -Release: 9%{?extraversion}%{?dist} +Release: 14%{?extraversion}%{?dist} Summary: A lightweight DHCP/caching DNS server Group: System Environment/Daemons @@ -61,6 +61,18 @@ Patch22: dnsmasq-2.76-min-query-port.patch Patch23: dnsmasq-2.76-dnssec-cache.patch # commit a997ca0da044719a0ce8a232d14da8b30022592b Patch24: dnsmasq-2.76-dnssec-passthru.patch +Patch25: dnsmasq-2.76-rh1721668-1.patch +Patch26: dnsmasq-2.76-rh1721668-2.patch +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 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -120,6 +132,14 @@ query/remove a DHCP server's leases. %patch22 -p1 -b .rh1614331 %patch23 -p1 -b .dnssec-cache %patch24 -p1 -b .dnssec-passthru +%patch25 -p1 -b .rh1721668-1 +%patch26 -p1 -b .rh1721668-2 +%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 # 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 @@ -206,6 +226,21 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man1/dhcp_* %changelog +* 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 +- Fix TCP queries after interface recreation (#1721668) + * Tue Mar 26 2019 Petr Menšík - 2.79-9 - Fix passing of dnssec enabled queries (#1638703)