diff --git a/backport-0001-Retry-on-interrupted-error-in-tftp.patch b/backport-0001-Retry-on-interrupted-error-in-tftp.patch new file mode 100644 index 0000000..f486f2d --- /dev/null +++ b/backport-0001-Retry-on-interrupted-error-in-tftp.patch @@ -0,0 +1,35 @@ +From f5f56c001dddd486859dc6301e6cbe00ba604fe8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 18 Aug 2021 10:09:35 +0200 +Subject: [PATCH 01/15] Retry on interrupted error in tftp + +Interrupt might arrive when sending error reply. Retry if possible. + +Wrong Check of Return Value + +10. dnsmasq-2.85/src/tftp.c:603: check_return: Calling "sendto(transfer->sockfd, dnsmasq_daemon->packet, len, 0, __CONST_SOCKADDR_ARG({.__sockaddr__ = &peer.sa}), sa_len(&peer))" without checking return value. This library function may fail and return an error code. + # 601| prettyprint_addr(&peer, daemon->addrbuff); + # 602| len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff); + # 603|-> sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer)); + # 604| } + # 605| } +--- + src/tftp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/tftp.c b/src/tftp.c +index 37bdff2..3d87523 100644 +--- a/src/tftp.c ++++ b/src/tftp.c +@@ -600,7 +600,7 @@ void check_tftp_listeners(time_t now) + /* Wrong source address. See rfc1350 para 4. */ + prettyprint_addr(&peer, daemon->addrbuff); + len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff); +- sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer)); ++ while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer)))); + } + } + } +-- +2.31.1 + diff --git a/backport-0002-Add-safety-checks-to-places-pointed-by-Coverity.patch b/backport-0002-Add-safety-checks-to-places-pointed-by-Coverity.patch new file mode 100644 index 0000000..8fc70a5 --- /dev/null +++ b/backport-0002-Add-safety-checks-to-places-pointed-by-Coverity.patch @@ -0,0 +1,77 @@ +From 061013293ceddce509ae06a31a045e803103f1ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 18 Aug 2021 14:59:23 +0200 +Subject: [PATCH 02/15] Add safety checks to places pointed by Coverity + +GCC Analyzer (experimental) + +1. dnsmasq-2.85/src/forward.c:0: scope_hint: In function 'allocate_rfd.part.0' +2. dnsmasq-2.85/src/forward.c:2321:18: warning[-Wanalyzer-null-dereference]: dereference of NULL 'rfd' + # 2319| *fdlp = rfl; + # 2320| + # 2321|-> return rfl->rfd->fd; + # 2322| } + # 2323| + +1. dnsmasq-2.85/src/cache.c:0: scope_hint: In function 'log_query' +2. dnsmasq-2.85/src/cache.c:1969:20: warning[-Wanalyzer-null-dereference]: dereference of NULL 'name' + # 1967| source = "cached"; + # 1968| + # 1969|-> if (strlen(name) == 0) + # 1970| name = "."; + # 1971| + +1. dnsmasq-2.85/src/cache.c:0: scope_hint: In function 'cache_scan_free' +2. dnsmasq-2.85/src/cache.c:436:20: warning[-Wanalyzer-null-argument]: use of NULL 'addr' where non-null expected +40. /usr/include/sys/un.h:37: included_from: Included from here. +41. dnsmasq-2.85/src/dnsmasq.h:101: included_from: Included from here. +42. dnsmasq-2.85/src/cache.c:17: included_from: Included from here. +43. /usr/include/string.h:64:12: note: argument 2 of 'memcmp' must be non-null + # 434| (flags & crecp->flags & F_REVERSE) && + # 435| (flags & crecp->flags & (F_IPV4 | F_IPV6)) && + # 436|-> memcmp(&crecp->addr, addr, addrlen) == 0) + # 437| { + # 438| *up = crecp->hash_next; +--- + src/cache.c | 4 ++-- + src/forward.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/cache.c b/src/cache.c +index 8add610..97c51a7 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -433,7 +433,7 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s + else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) && + (flags & crecp->flags & F_REVERSE) && + (flags & crecp->flags & (F_IPV4 | F_IPV6)) && +- memcmp(&crecp->addr, addr, addrlen) == 0) ++ addr && memcmp(&crecp->addr, addr, addrlen) == 0) + { + *up = crecp->hash_next; + cache_unlink(crecp); +@@ -2013,7 +2013,7 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg) + else + source = "cached"; + +- if (strlen(name) == 0) ++ if (name && !name[0]) + name = "."; + + if (option_bool(OPT_EXTRALOG)) +diff --git a/src/forward.c b/src/forward.c +index 3d638e4..f07c908 100644 +--- a/src/forward.c ++++ b/src/forward.c +@@ -2276,7 +2276,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv) + } + } + +- if (j == daemon->numrrand) ++ if (!rfd) /* should be when j == daemon->numrrand */ + { + struct randfd_list *rfl_poll; + +-- +2.31.1 + diff --git a/backport-0003-Small-safeguard-to-unexpected-data.patch b/backport-0003-Small-safeguard-to-unexpected-data.patch new file mode 100644 index 0000000..c496640 --- /dev/null +++ b/backport-0003-Small-safeguard-to-unexpected-data.patch @@ -0,0 +1,28 @@ +From 920cd815bafea084f68cc4309399aea77bd7f66b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 14:11:42 +0200 +Subject: [PATCH 03/15] Small safeguard to unexpected data + +Make sure negative index is not used for comparison. It seems code in +option parsing does not allow it to be empty, but insist on it also in +this place. +--- + src/dhcp-common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dhcp-common.c b/src/dhcp-common.c +index 73568a9..85b269a 100644 +--- a/src/dhcp-common.c ++++ b/src/dhcp-common.c +@@ -88,7 +88,7 @@ int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool) + for (; check; check = check->next) + { + const int check_len = strlen(check->net); +- const int is_wc = (check->net[check_len - 1] == '*'); ++ const int is_wc = (check_len > 0 && check->net[check_len - 1] == '*'); + + /* '#' for not is for backwards compat. */ + if (check->net[0] != '!' && check->net[0] != '#') +-- +2.31.1 + diff --git a/backport-0004-Fix-bunch-of-warnings-in-auth.c.patch b/backport-0004-Fix-bunch-of-warnings-in-auth.c.patch new file mode 100644 index 0000000..976255f --- /dev/null +++ b/backport-0004-Fix-bunch-of-warnings-in-auth.c.patch @@ -0,0 +1,153 @@ +From e61af561900b4d2dd976a575b2efd388be092742 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 16:00:35 +0200 +Subject: [PATCH 04/15] Fix bunch of warnings in auth.c + +Error: CLANG_WARNING: [#def7] +dnsmasq-2.86test7/src/auth.c:420:5: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 418| if (!found && is_name_synthetic(flag, name, &addr) ) + # 419| { + # 420|-> found = 1; + # 421| nxdomain = 0; + # 422| + +Error: CLANG_WARNING: [#def8] +dnsmasq-2.86test7/src/auth.c:436:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 434| { + # 435| auth = soa = 1; /* inhibits auth section */ + # 436|-> found = 1; + # 437| log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + # 438| } + +Error: CLANG_WARNING: [#def9] +dnsmasq-2.86test7/src/auth.c:472:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 470| ns = 1; /* ensure we include NS records! */ + # 471| axfr = 1; + # 472|-> found = 1; + # 473| axfroffset = nameoffset; + # 474| log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + +Error: CLANG_WARNING: [#def10] +dnsmasq-2.86test7/src/auth.c:480:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 478| auth = 1; + # 479| ns = 1; /* inhibits auth section */ + # 480|-> found = 1; + # 481| log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + # 482| } + +Error: CLANG_WARNING: [#def11] +dnsmasq-2.86test7/src/auth.c:501:4: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 499| log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid)); + # 500| *cut = 0; /* remove domain part */ + # 501|-> found = 1; + # 502| if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + # 503| daemon->auth_ttl, NULL, qtype, C_IN, + +Error: CLANG_WARNING: [#def12] +dnsmasq-2.86test7/src/auth.c:522:8: warning[deadcode.DeadStores]: Value stored to 'found' is never read + # 520| { + # 521| log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid)); + # 522|-> found = 1; + # 523| if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + # 524| daemon->auth_ttl, NULL, qtype, C_IN, + +Error: CLANG_WARNING: [#def13] +dnsmasq-2.86test7/src/auth.c:617:8: warning[deadcode.DeadStores]: Value stored to 'p' is never read + # 615| p += sprintf(p, "%u.", a & 0xff); + # 616| a = a >> 8; + # 617|-> p += sprintf(p, "%u.in-addr.arpa", a & 0xff); + # 618| + # 619| } + +Error: CPPCHECK_WARNING (CWE-758): [#def14] +dnsmasq-2.86test7/src/auth.c:627: warning[objectIndex]: The address of local variable 'addr6' might be accessed at non-zero index. + # 625| for (i = subnet->prefixlen-1; i >= 0; i -= 4) + # 626| { + # 627|-> int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3]; + # 628| p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); + # 629| } + +Error: CLANG_WARNING: [#def15] +dnsmasq-2.86test7/src/auth.c:630:8: warning[deadcode.DeadStores]: Value stored to 'p' is never read + # 628| p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); + # 629| } + # 630|-> p += sprintf(p, "ip6.arpa"); + # 631| + # 632| } +--- + src/auth.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/src/auth.c b/src/auth.c +index 172a4b2..4f03c39 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -417,7 +417,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + + if (!found && is_name_synthetic(flag, name, &addr) ) + { +- found = 1; + nxdomain = 0; + + log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL); +@@ -433,7 +432,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + if (qtype == T_SOA) + { + auth = soa = 1; /* inhibits auth section */ +- found = 1; + log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + } + else if (qtype == T_AXFR) +@@ -469,7 +467,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + soa = 1; /* inhibits auth section */ + ns = 1; /* ensure we include NS records! */ + axfr = 1; +- found = 1; + axfroffset = nameoffset; + log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + } +@@ -477,7 +474,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + { + auth = 1; + ns = 1; /* inhibits auth section */ +- found = 1; + log_query(F_RRNAME | F_AUTH, zone->domain, NULL, ""); + } + } +@@ -498,7 +494,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + *cut = '.'; /* restore domain part */ + log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid)); + *cut = 0; /* remove domain part */ +- found = 1; + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->auth_ttl, NULL, qtype, C_IN, + qtype == T_A ? "4" : "6", &crecp->addr)) +@@ -519,7 +514,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr)))) + { + log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid)); +- found = 1; + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + daemon->auth_ttl, NULL, qtype, C_IN, + qtype == T_A ? "4" : "6", &crecp->addr)) +@@ -614,7 +608,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + if (subnet->prefixlen >= 16 ) + p += sprintf(p, "%u.", a & 0xff); + a = a >> 8; +- p += sprintf(p, "%u.in-addr.arpa", a & 0xff); ++ sprintf(p, "%u.in-addr.arpa", a & 0xff); + + } + else +@@ -627,7 +621,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n + int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3]; + p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); + } +- p += sprintf(p, "ip6.arpa"); ++ sprintf(p, "ip6.arpa"); + + } + } +-- +2.31.1 + diff --git a/backport-0005-Fix-few-coverity-warnings-in-lease-tools.patch b/backport-0005-Fix-few-coverity-warnings-in-lease-tools.patch new file mode 100644 index 0000000..ab24440 --- /dev/null +++ b/backport-0005-Fix-few-coverity-warnings-in-lease-tools.patch @@ -0,0 +1,148 @@ +From be7f213066282baeed46cc34223601c462db9cbf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 16:32:05 +0200 +Subject: [PATCH 05/15] Fix few coverity warnings in lease-tools + +Error: UNINIT (CWE-457): [#def2] +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release.c:265: var_decl: Declaring variable "ifr" without initializer. +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release.c:285: uninit_use_in_call: Using uninitialized value "ifr". Field "ifr.ifr_ifru" is uninitialized when calling "setsockopt". + # 283| strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1); + # 284| ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; + # 285|-> if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) + # 286| { + # 287| perror("cannot setup interface"); + +Error: CHECKED_RETURN (CWE-252): [#def3] +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:346: check_return: Calling "inet_pton" without checking return value (as is done elsewhere 61 out of 72 times). +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:188: example_assign: Example 1: Assigning: "s" = return value from "inet_pton(10, ip, &result.ip)". +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:189: example_checked: Example 1 (cont.): "s" has its value checked in "s <= 0". +dnsmasq-2.86test7/src/cache.c:1108: example_checked: Example 2: "inet_pton(10, token, &addr)" has its value checked in "inet_pton(10, token, &addr) > 0". +dnsmasq-2.86test7/src/dbus.c:525: example_checked: Example 3: "inet_pton(2, ipaddr, &addr.addr4)" has its value checked in "inet_pton(2, ipaddr, &addr.addr4)". +dnsmasq-2.86test7/src/domain.c:138: example_checked: Example 4: "inet_pton(prot, tail, addr)" has its value checked in "inet_pton(prot, tail, addr)". +dnsmasq-2.86test7/src/lease.c:81: example_checked: Example 5: "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)" has its value checked in "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)". + # 344| client_addr.sin6_flowinfo = 0; + # 345| client_addr.sin6_scope_id =0; + # 346|-> inet_pton(AF_INET6, "::", &client_addr.sin6_addr); + # 347| bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)); + # 348| inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); + +Error: CHECKED_RETURN (CWE-252): [#def4] +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:347: check_return: Calling "bind(sock, (struct sockaddr *)&client_addr, 28U)" without checking return value. This library function may fail and return an error code. + # 345| client_addr.sin6_scope_id =0; + # 346| inet_pton(AF_INET6, "::", &client_addr.sin6_addr); + # 347|-> bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)); + # 348| inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); + # 349| server_addr.sin6_port = htons(DHCP6_SERVER_PORT); + +Error: CHECKED_RETURN (CWE-252): [#def5] +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:348: check_return: Calling "inet_pton" without checking return value (as is done elsewhere 61 out of 72 times). +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:188: example_assign: Example 1: Assigning: "s" = return value from "inet_pton(10, ip, &result.ip)". +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:189: example_checked: Example 1 (cont.): "s" has its value checked in "s <= 0". +dnsmasq-2.86test7/src/cache.c:1108: example_checked: Example 2: "inet_pton(10, token, &addr)" has its value checked in "inet_pton(10, token, &addr) > 0". +dnsmasq-2.86test7/src/dbus.c:525: example_checked: Example 3: "inet_pton(2, ipaddr, &addr.addr4)" has its value checked in "inet_pton(2, ipaddr, &addr.addr4)". +dnsmasq-2.86test7/src/domain.c:138: example_checked: Example 4: "inet_pton(prot, tail, addr)" has its value checked in "inet_pton(prot, tail, addr)". +dnsmasq-2.86test7/src/lease.c:81: example_checked: Example 5: "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)" has its value checked in "inet_pton(10, dnsmasq_daemon->namebuff, &addr.addr6)". + # 346| inet_pton(AF_INET6, "::", &client_addr.sin6_addr); + # 347| bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)); + # 348|-> inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); + # 349| server_addr.sin6_port = htons(DHCP6_SERVER_PORT); + # 350| int16_t recv_size = 0; + +Error: NEGATIVE_RETURNS (CWE-394): [#def6] +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:360: var_tested_neg: Variable "recv_size" tests negative. +dnsmasq-2.86test7/contrib/lease-tools/dhcp_release6.c:373: negative_returns: "recv_size" is passed to a parameter that cannot be negative. + # 371| } + # 372| + # 373|-> int16_t result = parse_packet(response, recv_size); + # 374| if (result == NOT_REPLY_CODE) + # 375| { +--- + contrib/lease-tools/dhcp_release.c | 1 + + contrib/lease-tools/dhcp_release6.c | 37 ++++++++++++++++++----------- + 2 files changed, 24 insertions(+), 14 deletions(-) + +diff --git a/contrib/lease-tools/dhcp_release.c b/contrib/lease-tools/dhcp_release.c +index c1c835b..84f5610 100644 +--- a/contrib/lease-tools/dhcp_release.c ++++ b/contrib/lease-tools/dhcp_release.c +@@ -280,6 +280,7 @@ int main(int argc, char **argv) + + /* This voodoo fakes up a packet coming from the correct interface, which really matters for + a DHCP server */ ++ memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1); + ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) +diff --git a/contrib/lease-tools/dhcp_release6.c b/contrib/lease-tools/dhcp_release6.c +index d680222..9b3438f 100644 +--- a/contrib/lease-tools/dhcp_release6.c ++++ b/contrib/lease-tools/dhcp_release6.c +@@ -318,6 +318,12 @@ void usage(const char* arg, FILE* stream) + fprintf (stream, "Usage: %s %s\n", arg, usage_string); + } + ++static void fail_fatal(const char *errstr, int exitcode) ++{ ++ perror(errstr); ++ exit(exitcode); ++} ++ + int send_release_packet(const char* iface, struct dhcp6_packet* packet) + { + struct sockaddr_in6 server_addr, client_addr; +@@ -343,18 +349,19 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet) + client_addr.sin6_port = htons(DHCP6_CLIENT_PORT); + client_addr.sin6_flowinfo = 0; + client_addr.sin6_scope_id =0; +- inet_pton(AF_INET6, "::", &client_addr.sin6_addr); +- bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)); +- inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr); ++ if (inet_pton(AF_INET6, "::", &client_addr.sin6_addr) <= 0) ++ fail_fatal("inet_pton", 5); ++ if (bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)) != 0) ++ perror("bind"); /* continue on bind error */ ++ if (inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr) <= 0) ++ fail_fatal("inet_pton", 5); + server_addr.sin6_port = htons(DHCP6_SERVER_PORT); +- int16_t recv_size = 0; ++ ssize_t recv_size = 0; ++ int result; + for (i = 0; i < 5; i++) + { + if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) +- { +- perror("sendto failed"); +- exit(4); +- } ++ fail_fatal("sendto failed", 4); + + recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0); + if (recv_size == -1) +@@ -367,16 +374,18 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet) + else + { + perror("recvfrom"); ++ result = UNSPEC_FAIL; + } + } +- +- int16_t result = parse_packet(response, recv_size); +- if (result == NOT_REPLY_CODE) ++ else + { +- sleep(1); +- continue; ++ result = parse_packet(response, recv_size); ++ if (result == NOT_REPLY_CODE) ++ { ++ sleep(1); ++ continue; ++ } + } +- + close(sock); + return result; + } +-- +2.31.1 + diff --git a/backport-0006-Fix-coverity-formats-issues-in-blockdata.patch b/backport-0006-Fix-coverity-formats-issues-in-blockdata.patch new file mode 100644 index 0000000..beb0898 --- /dev/null +++ b/backport-0006-Fix-coverity-formats-issues-in-blockdata.patch @@ -0,0 +1,48 @@ +From 3a077065ce846e301b532127ebecdd2771ad75ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 16:41:00 +0200 +Subject: [PATCH 06/15] Fix coverity formats issues in blockdata + +Error: PRINTF_ARGS (CWE-686): [#def16] +dnsmasq-2.86test7/src/blockdata.c:56: invalid_type: Argument "blockdata_count * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long". + # 54| { + # 55| my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"), + # 56|-> blockdata_count * sizeof(struct blockdata), + # 57| blockdata_hwm * sizeof(struct blockdata), + # 58| blockdata_alloced * sizeof(struct blockdata)); + +Error: PRINTF_ARGS (CWE-686): [#def17] +dnsmasq-2.86test7/src/blockdata.c:57: invalid_type: Argument "blockdata_hwm * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long". + # 55| my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"), + # 56| blockdata_count * sizeof(struct blockdata), + # 57|-> blockdata_hwm * sizeof(struct blockdata), + # 58| blockdata_alloced * sizeof(struct blockdata)); + # 59| } + +Error: PRINTF_ARGS (CWE-686): [#def18] +dnsmasq-2.86test7/src/blockdata.c:58: invalid_type: Argument "blockdata_alloced * 48UL" to format specifier "%u" was expected to have type "unsigned int" but has type "unsigned long". + # 56| blockdata_count * sizeof(struct blockdata), + # 57| blockdata_hwm * sizeof(struct blockdata), + # 58|-> blockdata_alloced * sizeof(struct blockdata)); + # 59| } + # 60| +--- + src/blockdata.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/blockdata.c b/src/blockdata.c +index f7740b5..0986285 100644 +--- a/src/blockdata.c ++++ b/src/blockdata.c +@@ -52,7 +52,7 @@ void blockdata_init(void) + + void blockdata_report(void) + { +- my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"), ++ my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"), + blockdata_count * sizeof(struct blockdata), + blockdata_hwm * sizeof(struct blockdata), + blockdata_alloced * sizeof(struct blockdata)); +-- +2.31.1 + diff --git a/backport-0007-Retry-dhcp6-ping-on-interrupts.patch b/backport-0007-Retry-dhcp6-ping-on-interrupts.patch new file mode 100644 index 0000000..1beb806 --- /dev/null +++ b/backport-0007-Retry-dhcp6-ping-on-interrupts.patch @@ -0,0 +1,32 @@ +From 467b621fb7da6e1318ac7204325b0adb01b3ff19 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 16:48:50 +0200 +Subject: [PATCH 07/15] Retry dhcp6 ping on interrupts + +Error: CHECKED_RETURN (CWE-252): [#def35] +dnsmasq-2.86test7/src/dhcp6.c:295: check_return: Calling "sendto(dnsmasq_daemon->icmp6fd, &neigh, 24UL, 0, __CONST_SOCKADDR_ARG({.__sockaddr__ = &addr.sa}), 28U)" without checking return value. This library function may fail and return an error code. + # 293| break; + # 294| + # 295|-> sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr)); + # 296| + # 297| ts.tv_sec = 0; +--- + src/dhcp6.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dhcp6.c b/src/dhcp6.c +index 2be877f..ae1f5c1 100644 +--- a/src/dhcp6.c ++++ b/src/dhcp6.c +@@ -292,7 +292,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi + if ((maclen = find_mac(&addr, mac, 0, now)) != 0) + break; + +- sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr)); ++ while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr)))); + + ts.tv_sec = 0; + ts.tv_nsec = 100000000; /* 100ms */ +-- +2.31.1 + diff --git a/backport-0008-Fix-coverity-warnings-on-dbus.patch b/backport-0008-Fix-coverity-warnings-on-dbus.patch new file mode 100644 index 0000000..fd02da5 --- /dev/null +++ b/backport-0008-Fix-coverity-warnings-on-dbus.patch @@ -0,0 +1,131 @@ +From bbfdf6a435cbd5f71ae76f962ce86786346589aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 17:19:05 +0200 +Subject: [PATCH 08/15] Fix coverity warnings on dbus + +Error: CLANG_WARNING: [#def30] +dnsmasq-2.86test7/src/dbus.c:117:3: warning[deadcode.DeadStores]: Value stored to 'w' is never read + # 115| daemon->watches = w; + # 116| + # 117|-> w = data; /* no warning */ + # 118| return TRUE; + # 119| } + +Error: CLANG_WARNING: [#def31] +dnsmasq-2.86test7/src/dbus.c:137:3: warning[deadcode.DeadStores]: Value stored to 'w' is never read + # 135| } + # 136| + # 137|-> w = data; /* no warning */ + # 138| } + # 139| + +Error: CHECKED_RETURN (CWE-252): [#def32] +dnsmasq-2.86test7/src/dbus.c:146: check_return: Calling "dbus_message_iter_init" without checking return value (as is done elsewhere 4 out of 5 times). +dnsmasq-2.86test7/src/dbus.c:460: example_checked: Example 1: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)". +dnsmasq-2.86test7/src/dbus.c:573: example_checked: Example 2: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)". +dnsmasq-2.86test7/src/dbus.c:257: example_checked: Example 3: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)". +dnsmasq-2.86test7/src/dbus.c:427: example_checked: Example 4: "dbus_message_iter_init(message, &iter)" has its value checked in "dbus_message_iter_init(message, &iter)". + # 144| char *domain; + # 145| + # 146|-> dbus_message_iter_init(message, &iter); + # 147| + # 148| mark_servers(SERV_FROM_DBUS); + +Error: NEGATIVE_RETURNS (CWE-394): [#def33] +dnsmasq-2.86test7/src/dbus.c:547: negative_return_fn: Function "parse_hex((char *)hwaddr, dhcp_chaddr, 16, NULL, &hw_type)" returns a negative number. +dnsmasq-2.86test7/src/dbus.c:547: assign: Assigning: "hw_len" = "parse_hex((char *)hwaddr, dhcp_chaddr, 16, NULL, &hw_type)". +dnsmasq-2.86test7/src/dbus.c:551: negative_returns: "hw_len" is passed to a parameter that cannot be negative. + # 549| hw_type = ARPHRD_ETHER; + # 550| + # 551|-> lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type, + # 552| clid_len, now, 0); + # 553| lease_set_expires(lease, expires, now); + +Error: CLANG_WARNING: [#def34] +dnsmasq-2.86test7/src/dbus.c:722:3: warning[deadcode.DeadStores]: Value stored to 'method' is never read + # 720| clear_cache_and_reload(dnsmasq_time()); + # 721| + # 722|-> method = user_data; /* no warning */ + # 723| + # 724| /* If no reply or no error, return nothing */ +--- + src/dbus.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/src/dbus.c b/src/dbus.c +index cbdce9c..d746b9a 100644 +--- a/src/dbus.c ++++ b/src/dbus.c +@@ -114,7 +114,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) + w->next = daemon->watches; + daemon->watches = w; + +- w = data; /* no warning */ ++ (void)data; /* no warning */ + return TRUE; + } + +@@ -134,16 +134,20 @@ static void remove_watch(DBusWatch *watch, void *data) + up = &(w->next); + } + +- w = data; /* no warning */ ++ (void)data; /* no warning */ + } + +-static void dbus_read_servers(DBusMessage *message) ++static DBusMessage* dbus_read_servers(DBusMessage *message) + { + DBusMessageIter iter; + union mysockaddr addr, source_addr; + char *domain; + +- dbus_message_iter_init(message, &iter); ++ if (!dbus_message_iter_init(message, &iter)) ++ { ++ return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, ++ "Failed to initialize dbus message iter"); ++ } + + mark_servers(SERV_FROM_DBUS); + +@@ -222,6 +226,7 @@ static void dbus_read_servers(DBusMessage *message) + + /* unlink and free anything still marked. */ + cleanup_servers(); ++ return NULL; + } + + #ifdef HAVE_LOOP +@@ -545,6 +550,10 @@ static DBusMessage *dbus_add_lease(DBusMessage* message) + "Invalid IP address '%s'", ipaddr); + + hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type); ++ if (hw_len < 0) ++ return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS, ++ "Invalid HW address '%s'", hwaddr); ++ + if (hw_type == 0 && hw_len != 0) + hw_type = ARPHRD_ETHER; + +@@ -668,7 +677,7 @@ DBusHandlerResult message_handler(DBusConnection *connection, + #endif + else if (strcmp(method, "SetServers") == 0) + { +- dbus_read_servers(message); ++ reply = dbus_read_servers(message); + new_servers = 1; + } + else if (strcmp(method, "SetServersEx") == 0) +@@ -719,7 +728,7 @@ DBusHandlerResult message_handler(DBusConnection *connection, + if (clear_cache) + clear_cache_and_reload(dnsmasq_time()); + +- method = user_data; /* no warning */ ++ (void)user_data; /* no warning */ + + /* If no reply or no error, return nothing */ + if (!reply) +-- +2.31.1 + diff --git a/backport-0009-Address-coverity-issues-detected-in-util.c.patch b/backport-0009-Address-coverity-issues-detected-in-util.c.patch new file mode 100644 index 0000000..cc075c7 --- /dev/null +++ b/backport-0009-Address-coverity-issues-detected-in-util.c.patch @@ -0,0 +1,110 @@ +From 7b975696a7bda5b86fcf168644f177544adb6fe9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 17:38:26 +0200 +Subject: [PATCH 09/15] Address coverity issues detected in util.c + +Error: CLANG_WARNING: [#def163] +dnsmasq-2.86test7/src/util.c:204:9: warning[deadcode.DeadStores]: Although the value stored to 'rc' is used in the enclosing expression, the value is never actually read from 'rc' + # 202| *nomem = 0; + # 203| + # 204|-> if (!(rc = check_name(in))) + # 205| return NULL; + # 206| + +Error: UNREACHABLE (CWE-561): [#def164] +dnsmasq-2.86test7/src/util.c:239: unreachable: This code cannot be reached: "if (ret = whine_malloc(strl...". + # 237| #endif + # 238| + # 239|-> if ((ret = whine_malloc(strlen(in)+1))) + # 240| strcpy(ret, in); + # 241| else if (nomem) + +Error: CLANG_WARNING: [#def165] +dnsmasq-2.86test7/src/util.c:531:2: warning[deadcode.DeadStores]: Value stored to 'p' is never read + # 529| p += sprintf(&buf[p], "%um", x); + # 530| if ((x = t%60)) + # 531|-> p += sprintf(&buf[p], "%us", x); + # 532| } + # 533| } + +Error: CPPCHECK_WARNING (CWE-456): [#def166] +dnsmasq-2.86test7/src/util.c:577: error[uninitvar]: Uninitialized variable: sav + # 575| for (j = 0; j < bytes; j++) + # 576| { + # 577|-> char sav = sav; + # 578| if (j < bytes - 1) + # 579| { + +Error: CLANG_WARNING: [#def167] +dnsmasq-2.86test7/src/util.c:577:9: warning[core.uninitialized.Assign]: Assigned value is garbage or undefined + # 575| for (j = 0; j < bytes; j++) + # 576| { + # 577|-> char sav = sav; + # 578| if (j < bytes - 1) + # 579| { + +Error: MISSING_RESTORE (CWE-573): [#def168] +dnsmasq-2.86test7/src/util.c:580: save: Saving non-local "in[(j + 1) * 2]" in local "sav". +dnsmasq-2.86test7/src/util.c:581: modify: Modifying non-local "in[(j + 1) * 2]". +dnsmasq-2.86test7/src/util.c:586: end_of_scope: Value of non-local "in[(j + 1) * 2]" that was saved in "sav" is not restored as it was along other paths. +dnsmasq-2.86test7/src/util.c:592: restore_example: The original value of non-local "in[(j + 1) * 2]" was restored here. + # 584| is illegal. */ + # 585| if (strchr(&in[j*2], '*')) + # 586|-> return -1; + # 587| out[i] = strtol(&in[j*2], NULL, 16); + # 588| mask = mask << 1; +--- + src/util.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/util.c b/src/util.c +index 1425764..8e69d55 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -208,6 +208,8 @@ char *canonicalise(char *in, int *nomem) + /* older libidn2 strips underscores, so don't do IDN processing + if the name has an underscore (check_name() returned 2) */ + if (rc != 2) ++#else ++ (void)rc; + #endif + #if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) + { +@@ -235,11 +237,14 @@ char *canonicalise(char *in, int *nomem) + return ret; + } + #endif +- ++ ++#if !defined(HAVE_LIBIDN2) || (defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)) ++ /* If recent libidn2 is used, it cannot reach this code. */ + if ((ret = whine_malloc(strlen(in)+1))) + strcpy(ret, in); + else if (nomem) +- *nomem = 1; ++ *nomem = 1; ++#endif + + return ret; + } +@@ -528,7 +533,7 @@ void prettyprint_time(char *buf, unsigned int t) + if ((x = (t/60)%60)) + p += sprintf(&buf[p], "%um", x); + if ((x = t%60)) +- p += sprintf(&buf[p], "%us", x); ++ sprintf(&buf[p], "%us", x); + } + } + +@@ -574,7 +579,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen, + int j, bytes = (1 + (r - in))/2; + for (j = 0; j < bytes; j++) + { +- char sav = sav; ++ char sav; + if (j < bytes - 1) + { + sav = in[(j+1)*2]; +-- +2.31.1 + diff --git a/backport-0010-Fix-coverity-detected-issues-in-option.c.patch b/backport-0010-Fix-coverity-detected-issues-in-option.c.patch new file mode 100644 index 0000000..a63ac41 --- /dev/null +++ b/backport-0010-Fix-coverity-detected-issues-in-option.c.patch @@ -0,0 +1,236 @@ +From db835f8c40e83c6392e69ffc7f2cc500f7682dd4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 19:23:20 +0200 +Subject: [PATCH 10/15] Fix coverity detected issues in option.c + +Error: STRING_OVERFLOW (CWE-120): [#def99] +dnsmasq-2.86test7/src/option.c:801: fixed_size_dest: You might overrun the 100-character fixed-size string "buff" by copying "usage[i].arg" without checking the length. +# 799| if (usage[i].arg) +# 800| { +# 801|-> strcpy(buff, usage[i].arg); +# 802| for (j = 0; tab[j].handle; j++) +# 803| if (tab[j].handle == *(usage[i].arg)) + +Error: CLANG_WARNING: [#def100] +dnsmasq-2.86test7/src/option.c:962:3: warning[deadcode.DeadStores]: Value stored to 'domain' is never read +# 960| } +# 961| +# 962|-> domain += sprintf(domain, "in-addr.arpa"); +# 963| +# 964| return 1; + +Error: CLANG_WARNING: [#def101] +dnsmasq-2.86test7/src/option.c:981:3: warning[deadcode.DeadStores]: Value stored to 'domain' is never read +# 979| domain += sprintf(domain, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); +# 980| } +# 981|-> domain += sprintf(domain, "ip6.arpa"); +# 982| +# 983| return 1; + +Error: RESOURCE_LEAK (CWE-772): [#def102] [important] +dnsmasq-2.86test7/src/option.c:1809: alloc_fn: Storage is returned from allocation function "opt_malloc". +dnsmasq-2.86test7/src/option.c:1809: var_assign: Assigning: "path" = storage returned from "opt_malloc(strlen(directory) + len + 2UL)". +dnsmasq-2.86test7/src/option.c:1810: noescape: Resource "path" is not freed or pointed-to in "strcpy". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1811: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1812: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1815: noescape: Resource "path" is not freed or pointed-to in "stat". +dnsmasq-2.86test7/src/option.c:1809: overwrite_var: Overwriting "path" in "path = opt_malloc(strlen(directory) + len + 2UL)" leaks the storage that "path" points to. +# 1807| continue; +# 1808| +# 1809|-> path = opt_malloc(strlen(directory) + len + 2); +# 1810| strcpy(path, directory); +# 1811| strcat(path, "/"); + +Error: RESOURCE_LEAK (CWE-772): [#def103] [important] +dnsmasq-2.86test7/src/option.c:1809: alloc_fn: Storage is returned from allocation function "opt_malloc". +dnsmasq-2.86test7/src/option.c:1809: var_assign: Assigning: "path" = storage returned from "opt_malloc(strlen(directory) + len + 2UL)". +dnsmasq-2.86test7/src/option.c:1810: noescape: Resource "path" is not freed or pointed-to in "strcpy". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1811: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1812: noescape: Resource "path" is not freed or pointed-to in "strcat". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/option.c:1815: noescape: Resource "path" is not freed or pointed-to in "stat". +dnsmasq-2.86test7/src/option.c:1858: leaked_storage: Variable "path" going out of scope leaks the storage it points to. +# 1856| free(files); +# 1857| } +# 1858|-> break; +# 1859| } +# 1860| + +Error: RESOURCE_LEAK (CWE-772): [#def104] [important] +dnsmasq-2.86test7/src/option.c:1996: alloc_fn: Storage is returned from allocation function "canonicalise_opt". +dnsmasq-2.86test7/src/option.c:1996: var_assign: Assigning: "name" = storage returned from "canonicalise_opt(arg)". +dnsmasq-2.86test7/src/option.c:1998: leaked_storage: Variable "name" going out of scope leaks the storage it points to. +# 1996| if (!(name = canonicalise_opt(arg)) || +# 1997| (comma && !(target = canonicalise_opt(comma)))) +# 1998|-> ret_err(_("bad MX name")); +# 1999| +# 2000| new = opt_malloc(sizeof(struct mx_srv_record)); + +Error: RESOURCE_LEAK (CWE-772): [#def106] [important] +dnsmasq-2.86test7/src/option.c:3477: alloc_fn: Storage is returned from allocation function "opt_malloc". +dnsmasq-2.86test7/src/option.c:3477: var_assign: Assigning: "new" = storage returned from "opt_malloc(96UL)". +dnsmasq-2.86test7/src/option.c:3618: leaked_storage: Variable "new" going out of scope leaks the storage it points to. +# 3616| sprintf(errstr, _("duplicate dhcp-host IP address %s"), +# 3617| daemon->addrbuff); +# 3618|-> return 0; +# 3619| } +# 3620| } + +Error: RESOURCE_LEAK (CWE-772): [#def108] [important] +dnsmasq-2.86test7/src/option.c:3781: alloc_fn: Storage is returned from allocation function "opt_malloc". +dnsmasq-2.86test7/src/option.c:3781: var_assign: Assigning: "new" = storage returned from "opt_malloc(32UL)". +dnsmasq-2.86test7/src/option.c:3786: leaked_storage: Variable "new" going out of scope leaks the storage it points to. +# 3784| +# 3785| if (!(comma = split(arg)) || (len = strlen(comma)) == 0) +# 3786|-> ret_err(gen_err); +# 3787| +# 3788| new->wildcard = 0; + +Error: RESOURCE_LEAK (CWE-772): [#def109] [important] +dnsmasq-2.86test7/src/option.c:3921: alloc_fn: Storage is returned from allocation function "opt_malloc". +dnsmasq-2.86test7/src/option.c:3921: var_assign: Assigning: "new" = storage returned from "opt_malloc(56UL)". +dnsmasq-2.86test7/src/option.c:3994: leaked_storage: Variable "new" going out of scope leaks the storage it points to. +# 3992| } +# 3993| +# 3994|-> ret_err(gen_err); +# 3995| } +# 3996| + +Error: CLANG_WARNING: [#def111] +dnsmasq-2.86test7/src/option.c:4693:25: warning[deadcode.DeadStores]: Value stored to 'tmp' during its initialization is never read +# 4691| if (!canon) +# 4692| { +# 4693|-> struct name_list *tmp = new->names, *next; +# 4694| for (tmp = new->names; tmp; tmp = next) +# 4695| +--- + src/option.c | 33 +++++++++++++++++++++------------ + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/src/option.c b/src/option.c +index ffce9fc..11655fd 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -798,7 +798,7 @@ static void do_usage(void) + + if (usage[i].arg) + { +- strcpy(buff, usage[i].arg); ++ safe_strncpy(buff, usage[i].arg, sizeof(buff)); + for (j = 0; tab[j].handle; j++) + if (tab[j].handle == *(usage[i].arg)) + sprintf(buff, "%d", tab[j].val); +@@ -959,7 +959,7 @@ static int domain_rev4(char *domain, struct in_addr addr, int msize) + return 0; + } + +- domain += sprintf(domain, "in-addr.arpa"); ++ sprintf(domain, "in-addr.arpa"); + + return 1; + } +@@ -978,7 +978,7 @@ static int domain_rev6(char *domain, struct in6_addr *addr, int msize) + int dig = ((unsigned char *)addr)[i>>3]; + domain += sprintf(domain, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); + } +- domain += sprintf(domain, "ip6.arpa"); ++ sprintf(domain, "ip6.arpa"); + + return 1; + } +@@ -1829,6 +1829,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + new->next = li; + *up = new; + } ++ else ++ free(path); + + } + +@@ -1995,7 +1997,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + + if (!(name = canonicalise_opt(arg)) || + (comma && !(target = canonicalise_opt(comma)))) +- ret_err(_("bad MX name")); ++ { ++ free(name); ++ free(target); ++ ret_err(_("bad MX name")); ++ } + + new = opt_malloc(sizeof(struct mx_srv_record)); + new->next = daemon->mxnames; +@@ -3616,6 +3622,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + inet_ntop(AF_INET, &in, daemon->addrbuff, ADDRSTRLEN); + sprintf(errstr, _("duplicate dhcp-host IP address %s"), + daemon->addrbuff); ++ dhcp_config_free(new); + return 0; + } + } +@@ -3779,16 +3786,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + + case LOPT_NAME_MATCH: /* --dhcp-name-match */ + { +- struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name)); +- struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid)); ++ struct dhcp_match_name *new; + ssize_t len; + + if (!(comma = split(arg)) || (len = strlen(comma)) == 0) + ret_err(gen_err); + ++ new = opt_malloc(sizeof(struct dhcp_match_name)); + new->wildcard = 0; +- new->netid = id; +- id->net = opt_string_alloc(set_prefix(arg)); ++ new->netid = opt_malloc(sizeof(struct dhcp_netid)); ++ new->netid->net = opt_string_alloc(set_prefix(arg)); + + if (comma[len-1] == '*') + { +@@ -3992,6 +3999,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + } + } + ++ dhcp_netid_free(new->netid); ++ free(new); + ret_err(gen_err); + } + +@@ -4367,7 +4376,7 @@ err: + case LOPT_CNAME: /* --cname */ + { + struct cname *new; +- char *alias, *target, *last, *pen; ++ char *alias, *target=NULL, *last, *pen; + int ttl = -1; + + for (last = pen = NULL, comma = arg; comma; comma = split(comma)) +@@ -4382,13 +4391,13 @@ err: + if (pen != arg && atoi_check(last, &ttl)) + last = pen; + +- target = canonicalise_opt(last); +- + while (arg != last) + { + int arglen = strlen(arg); + alias = canonicalise_opt(arg); + ++ if (!target) ++ target = canonicalise_opt(last); + if (!alias || !target) + { + free(target); +@@ -4691,7 +4700,7 @@ err: + struct name_list *nl; + if (!canon) + { +- struct name_list *tmp = new->names, *next; ++ struct name_list *tmp, *next; + for (tmp = new->names; tmp; tmp = next) + { + next = tmp->next; +-- +2.31.1 + diff --git a/backport-0011-Fix-coverity-detected-issue-in-radv.c.patch b/backport-0011-Fix-coverity-detected-issue-in-radv.c.patch new file mode 100644 index 0000000..845de43 --- /dev/null +++ b/backport-0011-Fix-coverity-detected-issue-in-radv.c.patch @@ -0,0 +1,54 @@ +From 9c088b29dcdb8a3e013120d8272a6e0314a8f3df Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 19:29:23 +0200 +Subject: [PATCH 11/15] Fix coverity detected issue in radv.c + +Error: NULL_RETURNS (CWE-476): [#def114] +dnsmasq-2.86test7/src/radv.c:748: returned_null: "expand" returns "NULL" (checked 10 out of 11 times). +dnsmasq-2.86test7/src/radv.c:748: var_assigned: Assigning: "p" = "NULL" return value from "expand". +dnsmasq-2.86test7/src/radv.c:749: dereference: Dereferencing a pointer that might be "NULL" "p" when calling "memset". [Note: The source code implementation of the function has been overridden by a builtin model.] +dnsmasq-2.86test7/src/outpacket.c:83: example_checked: Example 1: "expand(len)" has its value checked in "p = expand(len)". +dnsmasq-2.86test7/src/outpacket.c:109: example_checked: Example 2: "expand(1UL)" has its value checked in "p = expand(1UL)". +dnsmasq-2.86test7/src/radv.c:269: example_checked: Example 3: "expand(16UL)" has its value checked in "ra = expand(16UL)". +dnsmasq-2.86test7/src/radv.c:363: example_checked: Example 4: "expand(32UL)" has its value checked in "opt = expand(32UL)". +dnsmasq-2.86test7/src/radv.c:708: example_checked: Example 5: "expand(32UL)" has its value checked in "opt = expand(32UL)". + # 747| int len = (maclen + 9) >> 3; + # 748| unsigned char *p = expand(len << 3); + # 749|-> memset(p, 0, len << 3); + # 750| *p++ = ICMP6_OPT_SOURCE_MAC; + # 751| *p++ = len; + +Error: NULL_RETURNS (CWE-476): [#def115] +dnsmasq-2.86test7/src/radv.c:748: returned_null: "expand" returns "NULL" (checked 10 out of 11 times). +dnsmasq-2.86test7/src/radv.c:748: var_assigned: Assigning: "p" = "NULL" return value from "expand". +dnsmasq-2.86test7/src/radv.c:750: dereference: Incrementing a pointer which might be null: "p". +dnsmasq-2.86test7/src/outpacket.c:83: example_checked: Example 1: "expand(len)" has its value checked in "p = expand(len)". +dnsmasq-2.86test7/src/outpacket.c:109: example_checked: Example 2: "expand(1UL)" has its value checked in "p = expand(1UL)". +dnsmasq-2.86test7/src/radv.c:269: example_checked: Example 3: "expand(16UL)" has its value checked in "ra = expand(16UL)". +dnsmasq-2.86test7/src/radv.c:363: example_checked: Example 4: "expand(32UL)" has its value checked in "opt = expand(32UL)". +dnsmasq-2.86test7/src/radv.c:708: example_checked: Example 5: "expand(32UL)" has its value checked in "opt = expand(32UL)". + # 748| unsigned char *p = expand(len << 3); + # 749| memset(p, 0, len << 3); + # 750|-> *p++ = ICMP6_OPT_SOURCE_MAC; + # 751| *p++ = len; + # 752| memcpy(p, mac, maclen); +--- + src/radv.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/radv.c b/src/radv.c +index 3255904..6d6fa32 100644 +--- a/src/radv.c ++++ b/src/radv.c +@@ -746,6 +746,8 @@ static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void + add 7 to round up */ + int len = (maclen + 9) >> 3; + unsigned char *p = expand(len << 3); ++ if (!p) ++ return 1; + memset(p, 0, len << 3); + *p++ = ICMP6_OPT_SOURCE_MAC; + *p++ = len; +-- +2.31.1 + diff --git a/backport-0012-Fix-coverity-detected-issues-in-cache.c.patch b/backport-0012-Fix-coverity-detected-issues-in-cache.c.patch new file mode 100644 index 0000000..e88c64a --- /dev/null +++ b/backport-0012-Fix-coverity-detected-issues-in-cache.c.patch @@ -0,0 +1,41 @@ +From 957b2b25238d82a6c3afced2ff0423ad171fb22e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 20:10:37 +0200 +Subject: [PATCH 12/15] Fix coverity detected issues in cache.c + +Error: UNINIT (CWE-457): [#def27] +dnsmasq-2.86test7/src/cache.c:1193: var_decl: Declaring variable "lrec" without initializer. +dnsmasq-2.86test7/src/cache.c:1315: uninit_use_in_call: Using uninitialized value "lrec.ttd" when calling "make_non_terminals". + # 1313| { + # 1314| lrec.name.namep = txt->name; + # 1315|-> make_non_terminals(&lrec); + # 1316| } + # 1317| + +Error: CLANG_WARNING: [#def29] +dnsmasq-2.86test7/src/cache.c:1552:15: warning[core.uninitialized.Assign]: Assigned value is garbage or undefined + # 1550| { + # 1551| crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE); + # 1552|-> crecp->ttd = source->ttd; + # 1553| crecp->name.namep = name; + # 1554| +--- + src/cache.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cache.c b/src/cache.c +index 97c51a7..6722fa6 100644 +--- a/src/cache.c ++++ b/src/cache.c +@@ -1188,7 +1188,7 @@ void cache_reload(void) + struct host_record *hr; + struct name_list *nl; + struct cname *a; +- struct crec lrec; ++ struct crec lrec = { 0, }; + struct mx_srv_record *mx; + struct txt_record *txt; + struct interface_name *intr; +-- +2.31.1 + diff --git a/backport-0013-Fix-coverity-issues-detected-in-domain-match.c.patch b/backport-0013-Fix-coverity-issues-detected-in-domain-match.c.patch new file mode 100644 index 0000000..60df62b --- /dev/null +++ b/backport-0013-Fix-coverity-issues-detected-in-domain-match.c.patch @@ -0,0 +1,134 @@ +From 0dafe990a1395d597bc6022c3936769f7a0ddea7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 21:16:22 +0200 +Subject: [PATCH 13/15] Fix coverity issues detected in domain-match.c + +Error: CHECKED_RETURN (CWE-252): [#def28] +dnsmasq-2.86rc3/src/domain-match.c:414: check_return: Calling "add_resource_record" without checking return value (as is done elsewhere 44 out of 46 times). +dnsmasq-2.86rc3/src/auth.c:214: example_checked: Example 1: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)". +dnsmasq-2.86rc3/src/auth.c:239: example_checked: Example 2: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)". +dnsmasq-2.86rc3/src/rfc1035.c:1463: example_checked: Example 3: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)". +dnsmasq-2.86rc3/src/rfc1035.c:1500: example_checked: Example 4: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)". +dnsmasq-2.86rc3/src/rfc1035.c:2021: example_checked: Example 5: "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)" has its value checked in "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)". + # 412| + # 413| header->ancount = htons(ntohs(header->ancount) + 1); + # 414|-> add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr); + # 415| log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL); + # 416| } + +Error: CHECKED_RETURN (CWE-252): [#def29] +dnsmasq-2.86rc3/src/domain-match.c:429: check_return: Calling "add_resource_record" without checking return value (as is done elsewhere 44 out of 46 times). +dnsmasq-2.86rc3/src/auth.c:214: example_checked: Example 1: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", intr->name)". +dnsmasq-2.86rc3/src/auth.c:239: example_checked: Example 2: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, dnsmasq_daemon->auth_ttl, NULL, 12, 1, "d", name)". +dnsmasq-2.86rc3/src/rfc1035.c:1463: example_checked: Example 3: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, crec_ttl(crecp, now), &nameoffset, 5, 1, "d", cname_target)". +dnsmasq-2.86rc3/src/rfc1035.c:1500: example_checked: Example 4: "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)" has its value checked in "add_resource_record(header, limit, &trunc, nameoffset, &ansp, ttl, NULL, 16, t->class, "t", t->len, t->txt)". +dnsmasq-2.86rc3/src/rfc1035.c:2021: example_checked: Example 5: "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)" has its value checked in "add_resource_record(header, limit, NULL, rec->offset, &ansp, crec_ttl(crecp, now), NULL, type, 1, ((crecp->flags & 0x80U) ? "4" : "6"), &crecp->addr)". + # 427| + # 428| header->ancount = htons(ntohs(header->ancount) + 1); + # 429|-> add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr); + # 430| log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL); + # 431| } + +Error: NULL_RETURNS (CWE-476): [#def30] +dnsmasq-2.86rc3/src/domain-match.c:611: returned_null: "whine_malloc" returns "NULL" (checked 72 out of 76 times). +dnsmasq-2.86rc3/src/domain-match.c:611: var_assigned: Assigning: "alloc_domain" = "NULL" return value from "whine_malloc". +dnsmasq-2.86rc3/src/domain-match.c:620: dereference: Dereferencing a pointer that might be "NULL" "alloc_domain" when calling "hostname_isequal". +dnsmasq-2.86rc3/src/arp.c:88: example_checked: Example 1: "whine_malloc(48UL)" has its value checked in "arp = whine_malloc(48UL)". +dnsmasq-2.86rc3/src/blockdata.c:24: example_assign: Example 2: Assigning: "new" = return value from "whine_malloc(n * 48UL)". +dnsmasq-2.86rc3/src/blockdata.c:26: example_checked: Example 2 (cont.): "new" has its value checked in "new". +dnsmasq-2.86rc3/src/cache.c:1545: example_assign: Example 3: Assigning: "crecp" = return value from "whine_malloc(70UL)". +dnsmasq-2.86rc3/src/cache.c:1547: example_checked: Example 3 (cont.): "crecp" has its value checked in "crecp". +dnsmasq-2.86rc3/src/forward.c:1791: example_assign: Example 4: Assigning: "packet" = return value from "whine_malloc(66573UL)". +dnsmasq-2.86rc3/src/forward.c:1795: example_checked: Example 4 (cont.): "packet" has its value checked in "packet". +dnsmasq-2.86rc3/src/inotify.c:186: example_checked: Example 5: "whine_malloc(lendir + lenfile + 2UL)" has its value checked in "path = whine_malloc(lendir + lenfile + 2UL)". + # 618| if (flags & SERV_IS_LOCAL) + # 619| for (serv = daemon->servers; serv; serv = serv->next) + # 620|-> if ((serv->flags & SERV_MARK) && + # 621| hostname_isequal(alloc_domain, serv->domain)) + # 622| break; + +Error: RESOURCE_LEAK (CWE-772): [#def31] [important] +dnsmasq-2.86rc3/src/domain-match.c:611: alloc_fn: Storage is returned from allocation function "whine_malloc". +dnsmasq-2.86rc3/src/domain-match.c:611: var_assign: Assigning: "alloc_domain" = storage returned from "whine_malloc(1UL)". +dnsmasq-2.86rc3/src/domain-match.c:620: noescape: Resource "alloc_domain" is not freed or pointed-to in "hostname_isequal". +dnsmasq-2.86rc3/src/domain-match.c:646: leaked_storage: Variable "alloc_domain" going out of scope leaks the storage it points to. + # 644| + # 645| if (!(serv = whine_malloc(size))) + # 646|-> return 0; + # 647| + # 648| if (flags & SERV_IS_LOCAL) + +Error: NULL_RETURNS (CWE-476): [#def32] +dnsmasq-2.86rc3/src/domain-match.c:611: returned_null: "whine_malloc" returns "NULL" (checked 72 out of 76 times). +dnsmasq-2.86rc3/src/domain-match.c:611: var_assigned: Assigning: "alloc_domain" = "NULL" return value from "whine_malloc". +dnsmasq-2.86rc3/src/domain-match.c:674: dereference: Dereferencing a pointer that might be "NULL" "alloc_domain" when calling "strlen". +dnsmasq-2.86rc3/src/arp.c:88: example_checked: Example 1: "whine_malloc(48UL)" has its value checked in "arp = whine_malloc(48UL)". +dnsmasq-2.86rc3/src/blockdata.c:24: example_assign: Example 2: Assigning: "new" = return value from "whine_malloc(n * 48UL)". +dnsmasq-2.86rc3/src/blockdata.c:26: example_checked: Example 2 (cont.): "new" has its value checked in "new". +dnsmasq-2.86rc3/src/cache.c:1545: example_assign: Example 3: Assigning: "crecp" = return value from "whine_malloc(70UL)". +dnsmasq-2.86rc3/src/cache.c:1547: example_checked: Example 3 (cont.): "crecp" has its value checked in "crecp". +dnsmasq-2.86rc3/src/forward.c:1791: example_assign: Example 4: Assigning: "packet" = return value from "whine_malloc(66573UL)". +dnsmasq-2.86rc3/src/forward.c:1795: example_checked: Example 4 (cont.): "packet" has its value checked in "packet". +dnsmasq-2.86rc3/src/inotify.c:186: example_checked: Example 5: "whine_malloc(lendir + lenfile + 2UL)" has its value checked in "path = whine_malloc(lendir + lenfile + 2UL)". + # 672| serv->flags = flags; + # 673| serv->domain = alloc_domain; + # 674|-> serv->domain_len = strlen(alloc_domain); + # 675| + # 676| if (flags & SERV_4ADDR) +--- + src/domain-match.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/src/domain-match.c b/src/domain-match.c +index f8e4796..7124c18 100644 +--- a/src/domain-match.c ++++ b/src/domain-match.c +@@ -411,7 +411,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header + addr.addr4 = srv->addr; + + header->ancount = htons(ntohs(header->ancount) + 1); +- add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr); ++ if (!add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr)) ++ return 0; + log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL); + } + +@@ -426,7 +427,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header + addr.addr6 = srv->addr; + + header->ancount = htons(ntohs(header->ancount) + 1); +- add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr); ++ if (!add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr)) ++ return 0; + log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL); + } + +@@ -609,9 +611,11 @@ int add_update_server(int flags, + + if (*domain == 0) + alloc_domain = whine_malloc(1); +- else if (!(alloc_domain = canonicalise((char *)domain, NULL))) ++ else ++ alloc_domain = canonicalise((char *)domain, NULL); ++ if (!alloc_domain) + return 0; +- ++ + /* See if there is a suitable candidate, and unmark + only do this for forwarding servers, not + address or local, to avoid delays on large numbers. */ +@@ -643,7 +647,10 @@ int add_update_server(int flags, + size = sizeof(struct server); + + if (!(serv = whine_malloc(size))) +- return 0; ++ { ++ free(alloc_domain); ++ return 0; ++ } + + if (flags & SERV_IS_LOCAL) + { +-- +2.31.1 + diff --git a/backport-0014-Fix-coverity-detected-issues-in-dnsmasq.c.patch b/backport-0014-Fix-coverity-detected-issues-in-dnsmasq.c.patch new file mode 100644 index 0000000..6069244 --- /dev/null +++ b/backport-0014-Fix-coverity-detected-issues-in-dnsmasq.c.patch @@ -0,0 +1,133 @@ +From f476acbe3c2830e6ff0c50cc36d364a3f3f4fadb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 22:45:29 +0200 +Subject: [PATCH 14/15] Fix coverity detected issues in dnsmasq.c + +Error: DEADCODE (CWE-561): [#def12] +dnsmasq-2.86rc3/src/dnsmasq.c:37: assignment: Assigning: "bind_fallback" = "0". +dnsmasq-2.86rc3/src/dnsmasq.c:927: const: At condition "bind_fallback", the value of "bind_fallback" must be equal to 0. +dnsmasq-2.86rc3/src/dnsmasq.c:927: dead_error_condition: The condition "bind_fallback" cannot be true. +dnsmasq-2.86rc3/src/dnsmasq.c:928: dead_error_line: Execution cannot reach this statement: "my_syslog(4, "setting --bin...". +dnsmasq-2.86rc3/src/dnsmasq.c:928: effectively_constant: Local variable "bind_fallback" is assigned only once, to a constant value, making it effectively constant throughout its scope. If this is not the intent, examine the logic to see if there is a missing assignment that would make "bind_fallback" not remain constant. + # 926| + # 927| if (bind_fallback) + # 928|-> my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); + # 929| + # 930| if (option_bool(OPT_NOWILD)) + +Error: REVERSE_NEGATIVE (CWE-191): [#def13] +dnsmasq-2.86rc3/src/dnsmasq.c:383: negative_sink_in_call: Passing "dnsmasq_daemon->pxefd" to a parameter that cannot be negative. +dnsmasq-2.86rc3/src/dnsmasq.c:1086: check_after_sink: You might be using variable "dnsmasq_daemon->pxefd" before verifying that it is >= 0. + # 1084| { + # 1085| poll_listen(daemon->dhcpfd, POLLIN); + # 1086|-> if (daemon->pxefd != -1) + # 1087| poll_listen(daemon->pxefd, POLLIN); + # 1088| } + +Error: CHECKED_RETURN (CWE-252): [#def18] +dnsmasq-2.86rc3/src/dnsmasq.c:1582: check_return: Calling "fcntl(dnsmasq_daemon->helperfd, 4, i & 0xfffffffffffff7ff)" without checking return value. This library function may fail and return an error code. + # 1580| /* block in writes until all done */ + # 1581| if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1) + # 1582|-> fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); + # 1583| do { + # 1584| helper_write(); + +Error: CHECKED_RETURN (CWE-252): [#def22] +dnsmasq-2.86rc3/src/dnsmasq.c:1991: check_return: Calling "fcntl(confd, 4, flags & 0xfffffffffffff7ff)" without checking return value. This library function may fail and return an error code. + # 1989| Reset that here. */ + # 1990| if ((flags = fcntl(confd, F_GETFL, 0)) != -1) + # 1991|-> fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); + # 1992| + # 1993| buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns); + +Error: CHECKED_RETURN (CWE-252): [#def26] +dnsmasq-2.86rc3/src/dnssec.c:727: check_return: Calling "extract_name" without checking return value (as is done elsewhere 9 out of 10 times). +dnsmasq-2.86rc3/src/dnssec.c:459: example_checked: Example 1: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)". +dnsmasq-2.86rc3/src/dnssec.c:269: example_checked: Example 2: "extract_name(header, plen, &state->ip, state->buff, 1, 0)" has its value checked in "extract_name(header, plen, &state->ip, state->buff, 1, 0)". +dnsmasq-2.86rc3/src/dnssec.c:569: example_checked: Example 3: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)". +dnsmasq-2.86rc3/src/rfc1035.c:648: example_checked: Example 4: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)". +dnsmasq-2.86rc3/src/rfc1035.c:787: example_checked: Example 5: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)". + # 725| /* namebuff used for workspace above, restore to leave unchanged on exit */ + # 726| p = (unsigned char*)(rrset[0]); + # 727|-> extract_name(header, plen, &p, name, 1, 0); + # 728| + # 729| if (key) + +Error: CHECKED_RETURN (CWE-252): [#def27] +dnsmasq-2.86rc3/src/dnssec.c:1020: check_return: Calling "extract_name" without checking return value (as is done elsewhere 7 out of 8 times). +dnsmasq-2.86rc3/src/auth.c:140: example_checked: Example 1: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/dnssec.c:771: example_checked: Example 2: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/hash-questions.c:57: example_checked: Example 3: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/rfc1035.c:1028: example_checked: Example 4: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/rfc1035.c:1438: example_checked: Example 5: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". + # 1018| + # 1019| p = (unsigned char *)(header+1); + # 1020|-> extract_name(header, plen, &p, name, 1, 4); + # 1021| p += 4; /* qtype, qclass */ + # 1022| +--- + src/dnsmasq.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index 602daed..3e1bfe8 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -34,7 +34,6 @@ static void poll_resolv(int force, int do_reload, time_t now); + + int main (int argc, char **argv) + { +- int bind_fallback = 0; + time_t now; + struct sigaction sigact; + struct iname *if_tmp; +@@ -59,6 +58,8 @@ int main (int argc, char **argv) + int did_bind = 0; + struct server *serv; + char *netlink_warn; ++#else ++ int bind_fallback = 0; + #endif + #if defined(HAVE_DHCP) || defined(HAVE_DHCP6) + struct dhcp_context *context; +@@ -377,7 +378,7 @@ int main (int argc, char **argv) + bindtodevice(bound_device, daemon->dhcpfd); + did_bind = 1; + } +- if (daemon->enable_pxe && bound_device) ++ if (daemon->enable_pxe && bound_device && daemon->pxefd != -1) + { + bindtodevice(bound_device, daemon->pxefd); + did_bind = 1; +@@ -920,8 +921,10 @@ int main (int argc, char **argv) + my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), + daemon->log_file, strerror(log_err)); + ++#ifndef HAVE_LINUX_NETWORK + if (bind_fallback) + my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations")); ++#endif + + if (option_bool(OPT_NOWILD)) + warn_bound_listeners(); +@@ -1575,7 +1578,7 @@ static void async_event(int pipe, time_t now) + { + /* block in writes until all done */ + if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1) +- fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); ++ while(retry_send(fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK))); + do { + helper_write(); + } while (!helper_buf_empty() || do_script_run(now)); +@@ -1984,7 +1987,7 @@ static void check_dns_listeners(time_t now) + attribute from the listening socket. + Reset that here. */ + if ((flags = fcntl(confd, F_GETFL, 0)) != -1) +- fcntl(confd, F_SETFL, flags & ~O_NONBLOCK); ++ while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK))); + + buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns); + +-- +2.31.1 + diff --git a/backport-0015-Fix-coverity-issues-in-dnssec.c.patch b/backport-0015-Fix-coverity-issues-in-dnssec.c.patch new file mode 100644 index 0000000..67b1d6d --- /dev/null +++ b/backport-0015-Fix-coverity-issues-in-dnssec.c.patch @@ -0,0 +1,62 @@ +From 82c23fb1f0d9e46c6ce4bc4a57f0d377cc6089b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 3 Sep 2021 22:51:36 +0200 +Subject: [PATCH 15/15] Fix coverity issues in dnssec.c + +Error: CHECKED_RETURN (CWE-252): [#def26] +dnsmasq-2.86rc3/src/dnssec.c:727: check_return: Calling "extract_name" without checking return value (as is done elsewhere 9 out of 10 times). +dnsmasq-2.86rc3/src/dnssec.c:459: example_checked: Example 1: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)". +dnsmasq-2.86rc3/src/dnssec.c:269: example_checked: Example 2: "extract_name(header, plen, &state->ip, state->buff, 1, 0)" has its value checked in "extract_name(header, plen, &state->ip, state->buff, 1, 0)". +dnsmasq-2.86rc3/src/dnssec.c:569: example_checked: Example 3: "extract_name(header, plen, &p, keyname, 1, 0)" has its value checked in "extract_name(header, plen, &p, keyname, 1, 0)". +dnsmasq-2.86rc3/src/rfc1035.c:648: example_checked: Example 4: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)". +dnsmasq-2.86rc3/src/rfc1035.c:787: example_checked: Example 5: "extract_name(header, qlen, &p1, name, 1, 0)" has its value checked in "extract_name(header, qlen, &p1, name, 1, 0)". + # 725| /* namebuff used for workspace above, restore to leave unchanged on exit */ + # 726| p = (unsigned char*)(rrset[0]); + # 727|-> extract_name(header, plen, &p, name, 1, 0); + # 728| + # 729| if (key) + +Error: CHECKED_RETURN (CWE-252): [#def27] +dnsmasq-2.86rc3/src/dnssec.c:1020: check_return: Calling "extract_name" without checking return value (as is done elsewhere 7 out of 8 times). +dnsmasq-2.86rc3/src/auth.c:140: example_checked: Example 1: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/dnssec.c:771: example_checked: Example 2: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/hash-questions.c:57: example_checked: Example 3: "extract_name(header, plen, &p, name, 1, 4)" has its value checked in "extract_name(header, plen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/rfc1035.c:1028: example_checked: Example 4: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". +dnsmasq-2.86rc3/src/rfc1035.c:1438: example_checked: Example 5: "extract_name(header, qlen, &p, name, 1, 4)" has its value checked in "extract_name(header, qlen, &p, name, 1, 4)". + # 1018| + # 1019| p = (unsigned char *)(header+1); + # 1020|-> extract_name(header, plen, &p, name, 1, 4); + # 1021| p += 4; /* qtype, qclass */ + # 1022| +--- + src/dnssec.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/dnssec.c b/src/dnssec.c +index 94ebb6f..8800a5b 100644 +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -724,7 +724,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in + + /* namebuff used for workspace above, restore to leave unchanged on exit */ + p = (unsigned char*)(rrset[0]); +- extract_name(header, plen, &p, name, 1, 0); ++ if (!extract_name(header, plen, &p, name, 1, 0)) ++ return STAT_BOGUS; + + if (key) + { +@@ -1017,7 +1018,9 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char + } + + p = (unsigned char *)(header+1); +- extract_name(header, plen, &p, name, 1, 4); ++ if (!extract_name(header, plen, &p, name, 1, 4)) ++ return STAT_BOGUS; ++ + p += 4; /* qtype, qclass */ + + /* If the key needed to validate the DS is on the same domain as the DS, we'll +-- +2.31.1 + diff --git a/backport-Handle-DHCPREBIND-requests-in-the-DHCPv6-server.patch b/backport-Handle-DHCPREBIND-requests-in-the-DHCPv6-server.patch deleted file mode 100644 index c5819af..0000000 --- a/backport-Handle-DHCPREBIND-requests-in-the-DHCPv6-server.patch +++ /dev/null @@ -1,114 +0,0 @@ -From d55e2d086d1ff30c427fa5e0ecc79746de8a81b7 Mon Sep 17 00:00:00 2001 -From: Simon Kelley -Date: Fri, 9 Apr 2021 15:19:28 +0100 -Subject: [PATCH] Handle DHCPREBIND requests in the DHCPv6 server. - -Patch by srk, based on submitted patch from liaichun@huawei.com ---- - src/rfc3315.c | 60 +++++++++++++++++++++++++++++++++++---------------- - 1 files changed, 42 insertions(+), 18 deletions(-) - -diff --git a/src/rfc3315.c b/src/rfc3315.c -index 982c68a..5c2ff97 100644 ---- a/src/rfc3315.c -+++ b/src/rfc3315.c -@@ -919,11 +919,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - - - case DHCP6RENEW: -+ case DHCP6REBIND: - { -+ int address_assigned = 0; -+ - /* set reply message type */ - *outmsgtypep = DHCP6REPLY; - -- log6_quiet(state, "DHCPRENEW", NULL, NULL); -+ log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL); - - for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end)) - { -@@ -952,24 +955,35 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, - state->iaid, &req_addr))) - { -- /* If the server cannot find a client entry for the IA the server -- returns the IA containing no addresses with a Status Code option set -- to NoBinding in the Reply message. */ -- save_counter(iacntr); -- t1cntr = 0; -- -- log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found")); -- -- o1 = new_opt6(OPTION6_STATUS_CODE); -- put_opt6_short(DHCP6NOBINDING); -- put_opt6_string(_("no binding found")); -- end_opt6(o1); -- -- preferred_time = valid_time = 0; -- break; -+ if (msg_type == DHCP6REBIND) -+ { -+ /* When rebinding, we can create a lease if it doesn't exist. */ -+ lease = lease6_allocate(&req_addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA); -+ if (lease) -+ lease_set_iaid(lease, state->iaid); -+ else -+ break; -+ } -+ else -+ { -+ /* If the server cannot find a client entry for the IA the server -+ returns the IA containing no addresses with a Status Code option set -+ to NoBinding in the Reply message. */ -+ save_counter(iacntr); -+ t1cntr = 0; -+ -+ log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found")); -+ -+ o1 = new_opt6(OPTION6_STATUS_CODE); -+ put_opt6_short(DHCP6NOBINDING); -+ put_opt6_string(_("no binding found")); -+ end_opt6(o1); -+ -+ preferred_time = valid_time = 0; -+ break; -+ } - } - -- - if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) || - (this_context = address6_valid(state->context, &req_addr, tagif, 1))) - { -@@ -1000,6 +1014,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - - if (preferred_time == 0) - message = _("deprecated"); -+ -+ address_assigned = 1; - } - else - { -@@ -1022,10 +1038,18 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ - end_ia(t1cntr, min_time, 1); - end_opt6(o); - } -+ -+ if (!address_assigned && msg_type == DHCP6REBIND) -+ { -+ /* can't create lease for any address, return error */ -+ o1 = new_opt6(OPTION6_STATUS_CODE); -+ put_opt6_short(DHCP6NOADDRS); -+ put_opt6_string(_("no addresses available")); -+ end_opt6(o1); -+ } - - tagif = add_options(state, 0); - break; -- - } - - case DHCP6CONFIRM: --- -2.20.1 - diff --git a/dnsmasq-2.77-underflow.patch b/backport-dnsmasq-2.77-underflow.patch similarity index 100% rename from dnsmasq-2.77-underflow.patch rename to backport-dnsmasq-2.77-underflow.patch diff --git a/dnsmasq-2.78-fips.patch b/backport-dnsmasq-2.78-fips.patch similarity index 100% rename from dnsmasq-2.78-fips.patch rename to backport-dnsmasq-2.78-fips.patch diff --git a/backport-dnsmasq-2.81-configuration.patch b/backport-dnsmasq-2.81-configuration.patch new file mode 100644 index 0000000..f23aa2f --- /dev/null +++ b/backport-dnsmasq-2.81-configuration.patch @@ -0,0 +1,97 @@ +From 194e7521399048e37c5c2cff18b9c8d442b893ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 30 Jun 2020 18:06:29 +0200 +Subject: [PATCH] Modify upstream configuration to safe defaults + +Most important change would be to listen only on localhost. Default +configuration should not listen to request from remote hosts. Match also +user and paths to directories shipped in Fedora. +--- + dnsmasq.conf.example | 29 ++++++++++++++++++++++++----- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/dnsmasq.conf.example b/dnsmasq.conf.example +index bf19424..8b85f44 100644 +--- a/dnsmasq.conf.example ++++ b/dnsmasq.conf.example +@@ -22,7 +22,7 @@ + + # Uncomment these to enable DNSSEC validation and caching: + # (Requires dnsmasq to be built with DNSSEC option.) +-#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf ++#conf-file=/usr/share/dnsmasq/trust-anchors.conf + #dnssec + + # Replies which are not DNSSEC signed may be legitimate, because the domain +@@ -96,14 +96,16 @@ + + # If you want dnsmasq to change uid and gid to something other + # than the default, edit the following lines. +-#user= +-#group= ++user=dnsmasq ++group=dnsmasq + + # If you want dnsmasq to listen for DHCP and DNS requests only on + # specified interfaces (and the loopback) give the name of the + # interface (eg eth0) here. + # Repeat the line for more than one interface. + #interface= ++# Listen only on localhost by default ++interface=lo + # Or you can specify which interface _not_ to listen on + #except-interface= + # Or which to listen on by address (remember to include 127.0.0.1 if +@@ -114,6 +116,10 @@ + # disable DHCP and TFTP on it. + #no-dhcp-interface= + ++# Serve DNS and DHCP only to networks directly connected to this machine. ++# Any interface= line will override it. ++#local-service ++ + # On systems which support it, dnsmasq binds the wildcard address, + # even when it is listening on only some interfaces. It then discards + # requests that it shouldn't reply to. This has the advantage of +@@ -121,7 +127,16 @@ + # want dnsmasq to really bind only the interfaces it is listening on, + # uncomment this option. About the only time you may need this is when + # running another nameserver on the same machine. +-#bind-interfaces ++# ++# To listen only on localhost and do not receive packets on other ++# interfaces, bind only to lo device. Comment out to bind on single ++# wildcard socket. ++bind-interfaces ++ ++# Comment out above line and uncoment following 2 lines. ++# Update interface name, use ip link to get its name. ++#bind-dynamic ++#interface=eno1 + + # If you don't want dnsmasq to read /etc/hosts, uncomment the + # following line. +@@ -535,7 +550,7 @@ + # The DHCP server needs somewhere on disk to keep its lease database. + # This defaults to a sane location, but if you want to change it, use + # the line below. +-#dhcp-leasefile=/var/lib/misc/dnsmasq.leases ++#dhcp-leasefile=/var/lib/dnsmasq/dnsmasq.leases + + # Set the DHCP server to authoritative mode. In this mode it will barge in + # and take over the lease for any client which broadcasts on the network, +@@ -673,7 +688,11 @@ + # Include all files in a directory which end in .conf + #conf-dir=/etc/dnsmasq.d/,*.conf + ++# Include all files in /etc/dnsmasq.d except RPM backup files ++conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig ++ + # If a DHCP client claims that its name is "wpad", ignore that. + # This fixes a security hole. see CERT Vulnerability VU#598349 + #dhcp-name-match=set:wpad-ignore,wpad + #dhcp-ignore-names=tag:wpad-ignore ++ +-- +2.31.1 + diff --git a/backport-dnsmasq-2.85-lease-hostname.patch b/backport-dnsmasq-2.85-lease-hostname.patch new file mode 100644 index 0000000..849ae7c --- /dev/null +++ b/backport-dnsmasq-2.85-lease-hostname.patch @@ -0,0 +1,26 @@ +From bea12dc31409180f6cb3a0578c2340c0116ef003 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Fri, 2 Jul 2021 10:03:47 +0200 +Subject: [PATCH] Modify and propagate changed lease + +If hostname is reset on existing lease, propagate such change to leases +file and script. +--- + src/lease.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lease.c b/src/lease.c +index b56647d..1a9f1c6 100644 +--- a/src/lease.c ++++ b/src/lease.c +@@ -1021,6 +1021,7 @@ void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, ch + } + + kill_name(lease_tmp); ++ lease_tmp->flags |= LEASE_CHANGED; /* run script on change */ + break; + } + } +-- +2.31.1 + diff --git a/backport-dnsmasq-2.86-build_server_array.patch b/backport-dnsmasq-2.86-build_server_array.patch new file mode 100644 index 0000000..95b7bff --- /dev/null +++ b/backport-dnsmasq-2.86-build_server_array.patch @@ -0,0 +1,67 @@ +From 068e849c713fa5e95eeb210792c061b7e212eab5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Wed, 13 Oct 2021 16:58:39 +0200 +Subject: [PATCH] Ensure serverarray is rebuilt once server can be removed + +Because cleanup_servers is called from each place which can remove +server, use that function to refresh serverarray after changes. Make it +static, since it does not have to be called from other places. +--- + src/dnsmasq.h | 1 - + src/domain-match.c | 8 +++++++- + src/network.c | 1 - + 3 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 08f2785..3f82412 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1757,7 +1757,6 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio + #endif + + /* domain-match.c */ +-void build_server_array(void); + int lookup_domain(char *qdomain, int flags, int *lowout, int *highout); + int filter_servers(int seed, int flags, int *lowout, int *highout); + int is_local_answer(time_t now, int first, char *name); +diff --git a/src/domain-match.c b/src/domain-match.c +index 45528c1..e5b409e 100644 +--- a/src/domain-match.c ++++ b/src/domain-match.c +@@ -23,7 +23,7 @@ static int order_servers(struct server *s, struct server *s2); + /* If the server is USE_RESOLV or LITERAL_ADDRES, it lives on the local_domains chain. */ + #define SERV_IS_LOCAL (SERV_USE_RESOLV | SERV_LITERAL_ADDRESS) + +-void build_server_array(void) ++static void build_server_array(void) + { + struct server *serv; + int count = 0; +@@ -592,6 +592,12 @@ void cleanup_servers(void) + else + up = &serv->next; + } ++ ++ /* If we're delaying things, we don't call check_servers(), but ++ reload_servers() may have deleted some servers, rendering the server_array ++ invalid, so just rebuild that here. Once reload_servers() succeeds, ++ we call check_servers() above, which calls build_server_array itself. */ ++ build_server_array(); + } + + int add_update_server(int flags, +diff --git a/src/network.c b/src/network.c +index 3fc179d..0b68866 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -1653,7 +1653,6 @@ void check_servers(int no_loop_check) + } + + cleanup_servers(); /* remove servers we just deleted. */ +- build_server_array(); + } + + /* Return zero if no servers found, in that case we keep polling. +-- +2.31.1 + diff --git a/backport-dnsmasq-2.86-domain-match-local.patch b/backport-dnsmasq-2.86-domain-match-local.patch new file mode 100644 index 0000000..e398a19 --- /dev/null +++ b/backport-dnsmasq-2.86-domain-match-local.patch @@ -0,0 +1,274 @@ +From de372d6914ae20a1f9997815f258efbf3b14c39b Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Sat, 18 Sep 2021 23:01:12 +0100 +Subject: [PATCH] Fix confusion is server=/domain/# combined with + server|address=/domain/.... + +The 2.86 domain matching rewrite failed to take into account the possibilty that + +server=/example.com/# + +could be combined with, for example + +address=/example.com/1.2.3.4 + +resulting in the struct server datastructure for the former getting passed +to forward_query(), rapidly followed by a SEGV. + +This fix makes server=/example.com/# a fully fledged member of the +priority list, which is now IPv6 addr, IPv4 addr, all zero return, +resolvconf servers, upstream servers, no-data return + +Thanks to dl6er@dl6er.de for finding and characterising the bug. +--- + src/dnsmasq.h | 34 +++++++------- + src/domain-match.c | 113 +++++++++++++++++++++++---------------------- + 2 files changed, 75 insertions(+), 72 deletions(-) + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 56a3f1d..327ad65 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -530,23 +530,23 @@ union mysockaddr { + + + /* The actual values here matter, since we sort on them to get records in the order +- IPv6 addr, IPv4 addr, all zero return, no-data return, send upstream. */ +-#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next three flags */ +-#define SERV_ALL_ZEROS 2 /* return all zeros for A and AAAA */ +-#define SERV_4ADDR 4 /* addr is IPv4 */ +-#define SERV_6ADDR 8 /* addr is IPv6 */ +-#define SERV_HAS_SOURCE 16 /* source address defined */ +-#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */ +-#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */ +-#define SERV_FROM_DBUS 128 /* 1 if source is DBus */ +-#define SERV_MARK 256 /* for mark-and-delete and log code */ +-#define SERV_WILDCARD 512 /* domain has leading '*' */ +-#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */ +-#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */ +-#define SERV_FROM_FILE 4096 /* read from --servers-file */ +-#define SERV_LOOP 8192 /* server causes forwarding loop */ +-#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */ +-#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */ ++ IPv6 addr, IPv4 addr, all zero return, resolvconf servers, upstream server, no-data return */ ++#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next four flags */ ++#define SERV_USE_RESOLV 2 /* forward this domain in the normal way */ ++#define SERV_ALL_ZEROS 4 /* return all zeros for A and AAAA */ ++#define SERV_4ADDR 8 /* addr is IPv4 */ ++#define SERV_6ADDR 16 /* addr is IPv6 */ ++#define SERV_HAS_SOURCE 32 /* source address defined */ ++#define SERV_FOR_NODOTS 64 /* server for names with no domain part only */ ++#define SERV_WARNED_RECURSIVE 128 /* avoid warning spam */ ++#define SERV_FROM_DBUS 256 /* 1 if source is DBus */ ++#define SERV_MARK 512 /* for mark-and-delete and log code */ ++#define SERV_WILDCARD 1024 /* domain has leading '*' */ ++#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */ ++#define SERV_FROM_FILE 4096 /* read from --servers-file */ ++#define SERV_LOOP 8192 /* server causes forwarding loop */ ++#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */ ++#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */ + + struct serverfd { + int fd; +diff --git a/src/domain-match.c b/src/domain-match.c +index b22948c..8f29621 100644 +--- a/src/domain-match.c ++++ b/src/domain-match.c +@@ -207,16 +207,16 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout) + } + } + +- if (found) ++ if (found && filter_servers(try, flags, &nlow, &nhigh)) ++ /* We have a match, but it may only be (say) an IPv6 address, and ++ if the query wasn't for an AAAA record, it's no good, and we need ++ to continue generalising */ + { + /* We've matched a setting which says to use servers without a domain. + Continue the search with empty query */ +- if (daemon->serverarray[try]->flags & SERV_USE_RESOLV) ++ if (daemon->serverarray[nlow]->flags & SERV_USE_RESOLV) + crop_query = qlen; +- else if (filter_servers(try, flags, &nlow, &nhigh)) +- /* We have a match, but it may only be (say) an IPv6 address, and +- if the query wasn't for an AAAA record, it's no good, and we need +- to continue generalising */ ++ else + break; + } + } +@@ -273,7 +273,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) + nlow--; + + while (nhigh < daemon->serverarraysz-1 && order_servers(daemon->serverarray[nhigh], daemon->serverarray[nhigh+1]) == 0) +- nhigh++; ++ nhigh++; + + nhigh++; + +@@ -293,10 +293,10 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) + else + { + /* Now the servers are on order between low and high, in the order +- IPv6 addr, IPv4 addr, return zero for both, send upstream, no-data return. ++ IPv6 addr, IPv4 addr, return zero for both, resolvconf servers, send upstream, no-data return. + + See which of those match our query in that priority order and narrow (low, high) */ +- ++ + for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++); + + if (i != nlow && (flags & F_IPV6)) +@@ -321,32 +321,40 @@ int filter_servers(int seed, int flags, int *lowout, int *highout) + { + nlow = i; + +- /* now look for a server */ +- for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++); +- ++ /* Short to resolv.conf servers */ ++ for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++); ++ + if (i != nlow) +- { +- /* If we want a server that can do DNSSEC, and this one can't, +- return nothing, similarly if were looking only for a server +- for a particular domain. */ +- if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC)) +- nlow = nhigh; +- else if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0) +- nlow = nhigh; +- else +- nhigh = i; +- } ++ nhigh = i; + else + { +- /* --local=/domain/, only return if we don't need a server. */ +- if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER)) +- nhigh = i; ++ /* now look for a server */ ++ for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++); ++ ++ if (i != nlow) ++ { ++ /* If we want a server that can do DNSSEC, and this one can't, ++ return nothing, similarly if were looking only for a server ++ for a particular domain. */ ++ if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC)) ++ nlow = nhigh; ++ else if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0) ++ nlow = nhigh; ++ else ++ nhigh = i; ++ } ++ else ++ { ++ /* --local=/domain/, only return if we don't need a server. */ ++ if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER)) ++ nhigh = i; ++ } + } + } + } + } + } +- ++ + *lowout = nlow; + *highout = nhigh; + +@@ -521,10 +529,10 @@ static int order_qsort(const void *a, const void *b) + /* Sort all literal NODATA and local IPV4 or IPV6 responses together, + in a very specific order. We flip the SERV_LITERAL_ADDRESS bit + so the order is IPv6 literal, IPv4 literal, all-zero literal, +- upstream server, NXDOMAIN literal. */ ++ unqualified servers, upstream server, NXDOMAIN literal. */ + if (rc == 0) +- rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) - +- ((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS); ++ rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) - ++ ((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS); + + /* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */ + if (rc == 0) +@@ -634,7 +642,7 @@ int add_update_server(int flags, + { + size_t size; + +- if (flags & SERV_LITERAL_ADDRESS) ++ if (flags & SERV_IS_LOCAL) + { + if (flags & SERV_6ADDR) + size = sizeof(struct serv_addr6); +@@ -656,10 +664,19 @@ int add_update_server(int flags, + { + serv->next = daemon->local_domains; + daemon->local_domains = serv; ++ ++ if (flags & SERV_4ADDR) ++ ((struct serv_addr4*)serv)->addr = local_addr->addr4; ++ ++ if (flags & SERV_6ADDR) ++ ((struct serv_addr6*)serv)->addr = local_addr->addr6; + } + else + { + struct server *s; ++ ++ memset(serv, 0, sizeof(struct server)); ++ + /* Add to the end of the chain, for order */ + if (!daemon->servers) + daemon->servers = serv; +@@ -669,37 +686,23 @@ int add_update_server(int flags, + s->next = serv; + } + +- serv->next = NULL; ++#ifdef HAVE_LOOP ++ serv->uid = rand32(); ++#endif ++ ++ if (interface) ++ safe_strncpy(serv->interface, interface, sizeof(serv->interface)); ++ if (addr) ++ serv->addr = *addr; ++ if (source_addr) ++ serv->source_addr = *source_addr; + } + } + +- if (!(flags & SERV_IS_LOCAL)) +- memset(serv, 0, sizeof(struct server)); +- + serv->flags = flags; + serv->domain = alloc_domain; + serv->domain_len = strlen(alloc_domain); + +- if (flags & SERV_4ADDR) +- ((struct serv_addr4*)serv)->addr = local_addr->addr4; +- +- if (flags & SERV_6ADDR) +- ((struct serv_addr6*)serv)->addr = local_addr->addr6; +- +- if (!(flags & SERV_IS_LOCAL)) +- { +-#ifdef HAVE_LOOP +- serv->uid = rand32(); +-#endif +- +- if (interface) +- safe_strncpy(serv->interface, interface, sizeof(serv->interface)); +- if (addr) +- serv->addr = *addr; +- if (source_addr) +- serv->source_addr = *source_addr; +- } +- + return 1; + } + +-- +2.31.1 + diff --git a/backport-dnsmasq-2.87-tcp-strcasecmp.patch b/backport-dnsmasq-2.87-tcp-strcasecmp.patch new file mode 100644 index 0000000..8e15cff --- /dev/null +++ b/backport-dnsmasq-2.87-tcp-strcasecmp.patch @@ -0,0 +1,33 @@ +From 6ad1f6f44e77619eeb1f9f16e205c24a1dc3e68b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Thu, 14 Oct 2021 20:56:17 +0200 +Subject: [PATCH] Compare order case insensitive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +DNS labels are defined case insensitive. When queried over TCP, query +name is not put to lower case. Make it match even when domain differs +only by used case. + +Signed-off-by: Petr Menšík +--- + src/domain-match.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/domain-match.c b/src/domain-match.c +index e5b409e..3a69aa1 100644 +--- a/src/domain-match.c ++++ b/src/domain-match.c +@@ -495,7 +495,7 @@ static int order(char *qdomain, size_t qlen, struct server *serv) + if (qlen > dlen) + return -1; + +- return strcmp(qdomain, serv->domain); ++ return strcasecmp(qdomain, serv->domain); + } + + static int order_servers(struct server *s1, struct server *s2) +-- +2.31.1 + diff --git a/bugfix-allow-binding-mac-with-ipv6.patch b/bugfix-allow-binding-mac-with-ipv6.patch index 547a99c..80260b3 100644 --- a/bugfix-allow-binding-mac-with-ipv6.patch +++ b/bugfix-allow-binding-mac-with-ipv6.patch @@ -7,40 +7,39 @@ Conflict: NA Reference: NA --- - src/dnsmasq.c | 2 +- - src/dnsmasq.h | 4 ++- - src/option.c | 5 +++- - src/rfc3315.c | 35 +++++++++++++++++++++++++- - 4 files changed, 46 insertions(+) + src/dnsmasq.c | 1 + + src/dnsmasq.h | 4 +++- + src/option.c | 3 +++ + src/rfc3315.c | 35 ++++++++++++++++++++++++++++++++++- + 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq.c b/src/dnsmasq.c -index fc085eb..e44c360 100644 +index bbdcaae..6e65e92 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c -@@ -260,7 +260,7 @@ int main (int argc, char **argv) - if (daemon->dhcp6) +@@ -282,6 +282,7 @@ int main (int argc, char **argv) { daemon->doing_ra = option_bool(OPT_RA); -- -+ daemon->bind_mac_with_ip6 = option_bool(OPT_BIND_MAC_IP6); + ++ daemon->bind_mac_with_ip6 = option_bool(OPT_BIND_MAC_IP6); for (context = daemon->dhcp6; context; context = context->next) { if (context->flags & CONTEXT_DHCP) diff --git a/src/dnsmasq.h b/src/dnsmasq.h -index 68e6287..e7f1a0d 100644 +index 3f82412..f1d2521 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h -@@ -269,7 +269,8 @@ struct event_desc { - #define OPT_SINGLE_PORT 60 - #define OPT_LEASE_RENEW 61 - #define OPT_LOG_DEBUG 62 --#define OPT_LAST 63 -+#define OPT_BIND_MAC_IP6 63 -+#define OPT_LAST 64 +@@ -275,7 +275,8 @@ struct event_desc { + #define OPT_UMBRELLA_DEVID 64 + #define OPT_CMARK_ALST_EN 65 + #define OPT_QUIET_TFTP 66 +-#define OPT_LAST 67 ++#define OPT_BIND_MAC_IP6 67 ++#define OPT_LAST 68 #define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) -@@ -1049,6 +1050,7 @@ extern struct daemon { +@@ -1139,6 +1140,7 @@ extern struct daemon { int override; int enable_pxe; int doing_ra, doing_dhcp6; @@ -49,37 +48,35 @@ index 68e6287..e7f1a0d 100644 struct dhcp_netid_list *force_broadcast, *bootp_dynamic; struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs; diff --git a/src/option.c b/src/option.c -index 1f698da..f02d389 100644 +index 11655fd..9c407f4 100644 --- a/src/option.c +++ b/src/option.c -@@ -167,7 +167,8 @@ struct myoption { - #define LOPT_PXE_VENDOR 361 - #define LOPT_DYNHOST 362 - #define LOPT_LOG_DEBUG 363 -- -+#define LOPT_BIND_MAC_IP6 364 -+ +@@ -174,6 +174,7 @@ struct myoption { + #define LOPT_CMARK_ALST_EN 365 + #define LOPT_CMARK_ALST 366 + #define LOPT_QUIET_TFTP 367 ++#define LOPT_BIND_MAC_IP6 368 + #ifdef HAVE_GETOPT_LONG static const struct option opts[] = - #else -@@ -339,6 +340,7 @@ static const struct myoption opts[] = - { "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID }, - { "dynamic-host", 1, 0, LOPT_DYNHOST }, +@@ -353,6 +354,7 @@ static const struct myoption opts[] = { "log-debug", 0, 0, LOPT_LOG_DEBUG }, + { "umbrella", 2, 0, LOPT_UMBRELLA }, + { "quiet-tftp", 0, 0, LOPT_QUIET_TFTP }, + { "bind-mac-with-ip6", 0, 0 , LOPT_BIND_MAC_IP6 }, { NULL, 0, 0, 0 } }; -@@ -518,6 +520,7 @@ static struct { - { LOPT_DUMPFILE, ARG_ONE, "", gettext_noop("Path to debug packet dump file"), NULL }, - { LOPT_DUMPMASK, ARG_ONE, "", gettext_noop("Mask which packets to dump"), NULL }, +@@ -539,6 +541,7 @@ static struct { { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, + { LOPT_UMBRELLA, ARG_ONE, "[=]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL }, + { LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL }, + { LOPT_BIND_MAC_IP6, OPT_BIND_MAC_IP6, NULL, gettext_noop("Bind mac with ipv6 address. This is an experimental feature and it conflicts with rfc3315."), NULL }, { 0, 0, NULL, NULL, NULL } }; diff --git a/src/rfc3315.c b/src/rfc3315.c -index b3f0a0a..a5a092c 100644 +index 5c2ff97..b0e6e57 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -49,6 +49,7 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz); @@ -96,11 +93,11 @@ index b3f0a0a..a5a092c 100644 match_netid(c->filter, solicit_tags, plain_range) && - config_valid(config, c, &addr, state, now)) + config_valid(config, c, &addr, state, now) && -+ check_and_try_preempte_address(state, &addr, now, config)) ++ check_and_try_preempte_address(state, &addr, now, config)) { mark_config_used(state->context, &addr); if (have_config(config, CONFIG_TIME)) -@@ -1259,6 +1261,37 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ +@@ -1283,6 +1285,37 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ } @@ -140,3 +137,4 @@ index b3f0a0a..a5a092c 100644 void *oro; -- 2.23.0 + diff --git a/dnsmasq-2.85.tar.xz b/dnsmasq-2.85.tar.xz deleted file mode 100644 index c9ad70a..0000000 Binary files a/dnsmasq-2.85.tar.xz and /dev/null differ diff --git a/dnsmasq-2.86.tar.xz b/dnsmasq-2.86.tar.xz new file mode 100644 index 0000000..40a0b39 Binary files /dev/null and b/dnsmasq-2.86.tar.xz differ diff --git a/dnsmasq.service b/dnsmasq.service index 07fa92e..963d88d 100644 --- a/dnsmasq.service +++ b/dnsmasq.service @@ -1,9 +1,13 @@ [Unit] Description=DNS caching server. +Before=nss-lookup.target +Wants=nss-lookup.target After=network.target [Service] -ExecStart=/usr/sbin/dnsmasq -k +ExecStart=/usr/sbin/dnsmasq +Type=forking +PIDFile=/run/dnsmasq.pid [Install] WantedBy=multi-user.target diff --git a/dnsmasq.spec b/dnsmasq.spec index c62b96f..2c96f97 100644 --- a/dnsmasq.spec +++ b/dnsmasq.spec @@ -1,5 +1,5 @@ Name: dnsmasq -Version: 2.85 +Version: 2.86 Release: 1 Summary: Dnsmasq provides network infrastructure for small networks License: GPLv2 or GPLv3 @@ -8,11 +8,30 @@ Source0: http://www.thekelleys.org.uk/dnsmasq/%{name}-%{version}.tar.xz Source1: dnsmasq.service Source2: dnsmasq-systemd-sysusers.conf -Patch1: dnsmasq-2.77-underflow.patch -Patch2: dnsmasq-2.78-fips.patch -Patch3: bugfix-allow-binding-mac-with-ipv6.patch -Patch4: bugfix-deal-with-CONFRIM-when-binding-mac-with-ipv6.patch -Patch14: backport-Handle-DHCPREBIND-requests-in-the-DHCPv6-server.patch +Patch1: backport-dnsmasq-2.77-underflow.patch +Patch2: backport-dnsmasq-2.81-configuration.patch +Patch3: backport-dnsmasq-2.78-fips.patch +Patch4: backport-0001-Retry-on-interrupted-error-in-tftp.patch +Patch5: backport-0002-Add-safety-checks-to-places-pointed-by-Coverity.patch +Patch6: backport-0003-Small-safeguard-to-unexpected-data.patch +Patch7: backport-0004-Fix-bunch-of-warnings-in-auth.c.patch +Patch8: backport-0005-Fix-few-coverity-warnings-in-lease-tools.patch +Patch9: backport-0006-Fix-coverity-formats-issues-in-blockdata.patch +Patch10: backport-0007-Retry-dhcp6-ping-on-interrupts.patch +Patch11: backport-0008-Fix-coverity-warnings-on-dbus.patch +Patch12: backport-0009-Address-coverity-issues-detected-in-util.c.patch +Patch13: backport-0010-Fix-coverity-detected-issues-in-option.c.patch +Patch14: backport-0011-Fix-coverity-detected-issue-in-radv.c.patch +Patch15: backport-0012-Fix-coverity-detected-issues-in-cache.c.patch +Patch16: backport-0013-Fix-coverity-issues-detected-in-domain-match.c.patch +Patch17: backport-0014-Fix-coverity-detected-issues-in-dnsmasq.c.patch +Patch18: backport-0015-Fix-coverity-issues-in-dnssec.c.patch +Patch19: backport-dnsmasq-2.86-domain-match-local.patch +Patch20: backport-dnsmasq-2.86-build_server_array.patch +Patch21: backport-dnsmasq-2.87-tcp-strcasecmp.patch +Patch22: bugfix-allow-binding-mac-with-ipv6.patch +Patch23: bugfix-deal-with-CONFRIM-when-binding-mac-with-ipv6.patch + BuildRequires: gcc BuildRequires: dbus-devel pkgconfig libidn2-devel nettle-devel systemd @@ -42,15 +61,11 @@ for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do sed -i 's|/var/lib/misc/dnsmasq.leases|/var/lib/dnsmasq/dnsmasq.leases|g' "$file" done -sed -i 's|#user=|user=dnsmasq|;s|#group=|group=dnsmasq|;s|%%%%PREFIX%%%%|%{_prefix}|' dnsmasq.conf.example sed -i 's|#define CHGRP "dip"|#define CHGRP "dnsmasq"|' src/config.h sed -i 's|#define CHUSER "nobody"|#define CHUSER "dnsmasq"|' src/config.h +sed -i "s|\(#\s*define RUNFILE\) \"/var/run/dnsmasq.pid\"|\1 \"%{_rundir}/dnsmasq.pid\"|" src/config.h sed -i 's|^COPTS[[:space:]]*=|\0 -DHAVE_DBUS -DHAVE_LIBIDN2 -DHAVE_DNSSEC|' Makefile -cat << EOF >> dnsmasq.conf.example -conf-dir=/etc/dnsmasq.d,.rpmnew,.rpmsave,.rpmorig -EOF - %build %make_build CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" %make_build -C contrib/lease-tools CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS" @@ -106,6 +121,9 @@ install -Dpm644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysusersdir}/dnsmasq.conf %{_mandir}/man8/dnsmasq* %changelog +* Tue Mar 22 2022 yanglu - 2.86-1 +- update dnsmasq to 2.86 + * Wed Jul 14 2021 gaihuiying - 2.85-1 - update dnsmasq to 2.85