From 28bf40562f5bab664ad8beffa376369525587ea7 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 27 Sep 2022 08:18:40 -0400 Subject: [PATCH] import dnsmasq-2.79-24.el8 --- .../dnsmasq-2.79-server-domain-fixup.patch | 99 ++++++++++ SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch | 25 +++ ...sq-2.81-option6-ntp-server-suboption.patch | 161 ++++++++++++++++ SOURCES/dnsmasq-2.87-CVE-2022-0934.patch | 175 ++++++++++++++++++ SPECS/dnsmasq.spec | 22 ++- 5 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 SOURCES/dnsmasq-2.79-server-domain-fixup.patch create mode 100644 SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch create mode 100644 SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch create mode 100644 SOURCES/dnsmasq-2.87-CVE-2022-0934.patch diff --git a/SOURCES/dnsmasq-2.79-server-domain-fixup.patch b/SOURCES/dnsmasq-2.79-server-domain-fixup.patch new file mode 100644 index 0000000..ac90a8f --- /dev/null +++ b/SOURCES/dnsmasq-2.79-server-domain-fixup.patch @@ -0,0 +1,99 @@ +From 4c5cbdfb82e668268a5f3713fe119fb077667c8e Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Mon, 22 Aug 2022 21:59:42 +0200 +Subject: [PATCH] Ensure also server_domains_cleanup is called always + +Fixes issue in patch dnsmasq-2.79-server-domain-rh1919894.patch. + +When /etc/resolv.conf is changed, dnsmasq reloads used servers. But it +does not call cleanup of server domains in this case. It might cause +serv_domain->last_server to become non-null, but pointing released +server. Ensure it is checked before any cleanup_servers() action always +and from all other places, like dbus setting. + +Caused unending loop in forward_query function, rhbz#2106361. +--- + src/network.c | 49 +++++++++++++++++++++++++------------------------ + 1 file changed, 25 insertions(+), 24 deletions(-) + +diff --git a/src/network.c b/src/network.c +index 4d140bb..96668fb 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -1402,10 +1402,35 @@ void mark_servers(int flag) + } + } + ++static void server_domains_cleanup(void) ++{ ++ struct server_domain *sd, *tmp, **up; ++ ++ /* unlink and free anything still marked. */ ++ for (up = &daemon->server_domains, sd=*up; sd; sd = tmp) ++ { ++ tmp = sd->next; ++ if (sd->flags & SERV_MARK) ++ { ++ *up = sd->next; ++ if (sd->domain) ++ free(sd->domain); ++ free(sd); ++ } ++ else { ++ up = &sd->next; ++ if (sd->last_server && (sd->last_server->flags & SERV_MARK)) ++ sd->last_server = NULL; ++ } ++ } ++} ++ + void cleanup_servers(void) + { + struct server *serv, *tmp, **up; + ++ server_domains_cleanup(); ++ + /* unlink and free anything still marked. */ + for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp) + { +@@ -1428,29 +1453,6 @@ void cleanup_servers(void) + #endif + } + +-void server_domains_cleanup(void) +-{ +- struct server_domain *sd, *tmp, **up; +- +- /* unlink and free anything still marked. */ +- for (up = &daemon->server_domains, sd=*up; sd; sd = tmp) +- { +- tmp = sd->next; +- if (sd->flags & SERV_MARK) +- { +- *up = sd->next; +- if (sd->domain) +- free(sd->domain); +- free(sd); +- } +- else { +- up = &sd->next; +- if (sd->last_server && (sd->last_server->flags & SERV_MARK)) +- sd->last_server = NULL; +- } +- } +-} +- + void add_update_server(int flags, + union mysockaddr *addr, + union mysockaddr *source_addr, +@@ -1739,7 +1741,6 @@ void check_servers(void) + up = &sfd->next; + } + +- server_domains_cleanup(); + cleanup_servers(); + } + +-- +2.37.2 + diff --git a/SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch b/SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch new file mode 100644 index 0000000..48d0bba --- /dev/null +++ b/SOURCES/dnsmasq-2.81-linux-SIOCGSTAMP.patch @@ -0,0 +1,25 @@ +From 3052ce208acf602f0163166dcefb7330d537cedb Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Wed, 24 Jul 2019 17:34:48 +0100 +Subject: [PATCH] Fix build after y2038 changes in glib. + +SIOCGSTAMP is defined in linux/sockios.h, not asm/sockios.h now. +--- + src/dnsmasq.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index ff3204a..3ef04ad 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -137,6 +137,7 @@ typedef unsigned long long u64; + #endif + + #if defined(HAVE_LINUX_NETWORK) ++#include + #include + /* There doesn't seem to be a universally-available + userspace header for these. */ +-- +2.36.1 + diff --git a/SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch b/SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch new file mode 100644 index 0000000..187a0e7 --- /dev/null +++ b/SOURCES/dnsmasq-2.81-option6-ntp-server-suboption.patch @@ -0,0 +1,161 @@ +From 03936d309782da038a2982b08fce7be85d884f0e Mon Sep 17 00:00:00 2001 +From: Vladislav Grishenko +Date: Sun, 8 Mar 2020 15:34:34 +0000 +Subject: [PATCH] Add DHCPv6 ntp-server (56) option handling. + +There was discussion in the past regarding DHCPv6 NTP server option +which needs special subclassing per RFC5908. + +Patch adds support for unicast, multicast IPv6 address and for FQDN string, +preserving possibly used (as suggested earlier) hex value. + +Unfortunately it's still not fully free from limitations - only address list or +only fqdn value list is possible, not mixed due current +state option parsing & flagging. + +(cherry picked from commit dded78b2338147daf69064d6d48c16b12744e441) +--- + src/dhcp-common.c | 2 +- + src/dhcp6-protocol.h | 4 ++++ + src/option.c | 19 ++++++++++++++++--- + src/rfc3315.c | 24 ++++++++++++++++++++---- + 4 files changed, 41 insertions(+), 8 deletions(-) + +diff --git a/src/dhcp-common.c b/src/dhcp-common.c +index 368d686..242a5a1 100644 +--- a/src/dhcp-common.c ++++ b/src/dhcp-common.c +@@ -642,7 +642,7 @@ static const struct opttab_t opttab6[] = { + { "sntp-server", 31, OT_ADDR_LIST }, + { "information-refresh-time", 32, OT_TIME }, + { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME }, +- { "ntp-server", 56, 0 }, ++ { "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ }, + { "bootfile-url", 59, OT_NAME }, + { "bootfile-param", 60, OT_CSTRING }, + { "client-arch", 61, 2 | OT_DEC }, /* RFC 5970 */ +diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h +index fee5d28..05560e8 100644 +--- a/src/dhcp6-protocol.h ++++ b/src/dhcp6-protocol.h +@@ -59,12 +59,16 @@ + #define OPTION6_REMOTE_ID 37 + #define OPTION6_SUBSCRIBER_ID 38 + #define OPTION6_FQDN 39 ++#define OPTION6_NTP_SERVER 56 + #define OPTION6_CLIENT_MAC 79 + + /* replace this with the real number when allocated. + defining this also enables the relevant code. */ + /* #define OPTION6_PREFIX_CLASS 99 */ + ++#define NTP_SUBOPTION_SRV_ADDR 1 ++#define NTP_SUBOPTION_MC_ADDR 2 ++#define NTP_SUBOPTION_SRV_FQDN 3 + + #define DHCP6SUCCESS 0 + #define DHCP6UNSPEC 1 +diff --git a/src/option.c b/src/option.c +index 6fa7bbd..1382c55 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -1245,6 +1245,12 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) + if (!found_dig) + is_dec = is_addr = 0; + ++#ifdef HAVE_DHCP6 ++ /* NTP server option takes hex, addresses or FQDN */ ++ if (is6 && new->opt == OPTION6_NTP_SERVER && !is_hex) ++ opt_len |= is_addr6 ? OT_ADDR_LIST : OT_RFC1035_NAME; ++#endif ++ + /* We know that some options take addresses */ + if (opt_len & OT_ADDR_LIST) + { +@@ -1505,8 +1511,9 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) + } + else if (comma && (opt_len & OT_RFC1035_NAME)) + { +- unsigned char *p = NULL, *newp, *end; ++ unsigned char *p = NULL, *q, *newp, *end; + int len = 0; ++ int header_size = (is6 && new->opt == OPTION6_NTP_SERVER) ? 4 : 0; + arg = comma; + comma = split(arg); + +@@ -1516,7 +1523,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) + if (!dom) + goto_err(_("bad domain in dhcp-option")); + +- newp = opt_malloc(len + strlen(dom) + 2); ++ newp = opt_malloc(len + header_size + strlen(dom) + 2); + + if (p) + { +@@ -1525,8 +1532,14 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) + } + + p = newp; +- end = do_rfc1035_name(p + len, dom, NULL); ++ q = p + len; ++ end = do_rfc1035_name(q + header_size, dom, NULL); + *end++ = 0; ++ if (is6 && new->opt == OPTION6_NTP_SERVER) ++ { ++ PUTSHORT(NTP_SUBOPTION_SRV_FQDN, q); ++ PUTSHORT(end - q - 2, q); ++ } + len = end - p; + free(dom); + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 1f1aad8..0fa12ad 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -1380,23 +1380,39 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh) + + for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++) + { ++ struct in6_addr *p = NULL; ++ + if (IN6_IS_ADDR_UNSPECIFIED(a)) + { + if (!add_local_addrs(state->context)) +- put_opt6(state->fallback, IN6ADDRSZ); ++ p = state->fallback; + } + else if (IN6_IS_ADDR_ULA_ZERO(a)) + { + if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) +- put_opt6(state->ula_addr, IN6ADDRSZ); ++ p = state->ula_addr; + } + else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a)) + { + if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr)) +- put_opt6(state->ll_addr, IN6ADDRSZ); ++ p = state->ll_addr; ++ } ++ else ++ p = a; ++ ++ if (!p) ++ continue; ++ else if (opt_cfg->opt == OPTION6_NTP_SERVER) ++ { ++ if (IN6_IS_ADDR_MULTICAST(p)) ++ o1 = new_opt6(NTP_SUBOPTION_MC_ADDR); ++ else ++ o1 = new_opt6(NTP_SUBOPTION_SRV_ADDR); ++ put_opt6(p, IN6ADDRSZ); ++ end_opt6(o1); + } + else +- put_opt6(a, IN6ADDRSZ); ++ put_opt6(p, IN6ADDRSZ); + } + + end_opt6(o); +-- +2.36.1 + diff --git a/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch b/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch new file mode 100644 index 0000000..afc36bb --- /dev/null +++ b/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch @@ -0,0 +1,175 @@ +From b0cb924292daecc1cc89fbd3911373eb468fc8f1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= +Date: Tue, 22 Feb 2022 00:45:01 +0100 +Subject: [PATCH] Change message type by dedicated function + +Long-term pointer to beginning of message does not work well. I case +outpacket is reallocated in any new_opt6() section, original outmsgtypep +pointer becomes invalid. Instead of using that pointer use dedicated +function, which will change just the first byte of the message. + +This makes sure correct beginning of packet is always used. +--- + src/dnsmasq.h | 1 + + src/outpacket.c | 11 +++++++++++ + src/rfc3315.c | 29 ++++++++++++++--------------- + 3 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/src/dnsmasq.h b/src/dnsmasq.h +index 27ff86a..0749260 100644 +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -1563,6 +1563,7 @@ void put_opt6_long(unsigned int val); + void put_opt6_short(unsigned int val); + void put_opt6_char(unsigned int val); + void put_opt6_string(char *s); ++void put_msgtype6(unsigned int val); + #endif + + /* radv.c */ +diff --git a/src/outpacket.c b/src/outpacket.c +index d20bd33..1c8f1bc 100644 +--- a/src/outpacket.c ++++ b/src/outpacket.c +@@ -115,4 +115,15 @@ void put_opt6_string(char *s) + put_opt6(s, strlen(s)); + } + ++void put_msgtype6(unsigned int val) ++{ ++ if (outpacket_counter == 0) ++ put_opt6_char(val); ++ else ++ { ++ unsigned char *p = daemon->outpacket.iov_base; ++ *p = val; ++ } ++} ++ + #endif +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 554b1fe..1f1aad8 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -116,7 +116,6 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, + void *end = inbuff + sz; + void *opts = inbuff + 34; + int msg_type = *((unsigned char *)inbuff); +- unsigned char *outmsgtypep; + void *opt; + struct dhcp_vendor *vendor; + +@@ -178,9 +177,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, + return 0; + + /* copy header stuff into reply message and set type to reply */ +- if (!(outmsgtypep = put_opt6(inbuff, 34))) ++ if (!put_opt6(inbuff, 34)) + return 0; +- *outmsgtypep = DHCP6RELAYREPL; ++ put_msgtype6(DHCP6RELAYREPL); + + /* look for relay options and set tags if found. */ + for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next) +@@ -249,7 +248,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + struct dhcp_netid *tagif; + struct dhcp_config *config = NULL; + struct dhcp_netid known_id, iface_id, v6_id; +- unsigned char *outmsgtypep; ++ unsigned char *xid; + struct dhcp_vendor *vendor; + struct dhcp_context *context_tmp; + struct dhcp_mac *mac_opt; +@@ -286,10 +285,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + state->tags = &v6_id; + + /* copy over transaction-id, and save pointer to message type */ +- if (!(outmsgtypep = put_opt6(inbuff, 4))) ++ if (!(xid = put_opt6(inbuff, 4))) + return 0; + start_opts = save_counter(-1); +- state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16; ++ state->xid = xid[3] | xid[2] << 8 | xid[1] << 16; + + /* We're going to be linking tags from all context we use. + mark them as unused so we don't link one twice and break the list */ +@@ -336,7 +335,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE)) + + { +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + o1 = new_opt6(OPTION6_STATUS_CODE); + put_opt6_short(DHCP6USEMULTI); + put_opt6_string("Use multicast"); +@@ -600,11 +599,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + struct dhcp_netid *solicit_tags; + struct dhcp_context *c; + +- *outmsgtypep = DHCP6ADVERTISE; ++ put_msgtype6(DHCP6ADVERTISE); + + if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0)) + { +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + state->lease_allocate = 1; + o = new_opt6(OPTION6_RAPID_COMMIT); + end_opt6(o); +@@ -876,7 +875,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + int start = save_counter(-1); + + /* set reply message type */ +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + state->lease_allocate = 1; + + log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL); +@@ -992,7 +991,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + case DHCP6RENEW: + { + /* set reply message type */ +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + + log6_quiet(state, "DHCPRENEW", NULL, NULL); + +@@ -1104,7 +1103,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + int good_addr = 0; + + /* set reply message type */ +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + + log6_quiet(state, "DHCPCONFIRM", NULL, NULL); + +@@ -1168,7 +1167,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname); + if (ignore) + return 0; +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + tagif = add_options(state, 1); + break; + } +@@ -1177,7 +1176,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + case DHCP6RELEASE: + { + /* set reply message type */ +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + + log6_quiet(state, "DHCPRELEASE", NULL, NULL); + +@@ -1242,7 +1241,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + case DHCP6DECLINE: + { + /* set reply message type */ +- *outmsgtypep = DHCP6REPLY; ++ put_msgtype6(DHCP6REPLY); + + log6_quiet(state, "DHCPDECLINE", NULL, NULL); + +-- +2.34.1 + diff --git a/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec index 394d8a6..7d91171 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -13,7 +13,7 @@ Name: dnsmasq Version: 2.79 -Release: 21%{?extraversion:.%{extraversion}}%{?dist} +Release: 24%{?extraversion:.%{extraversion}}%{?dist} Summary: A lightweight DHCP/caching DNS server License: GPLv2 or GPLv3 @@ -73,6 +73,13 @@ Patch33: dnsmasq-2.86-dhcpv6-client-arch.patch # Similar functionality is implemented since 2.86 in upstream, but introduced # several regressions. This implements just limited change in different way. Patch34: dnsmasq-2.79-server-domain-rh1919894.patch +Patch35: dnsmasq-2.87-CVE-2022-0934.patch +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=dded78b2338147daf69064d6d48c16b12744e441 +Patch36: dnsmasq-2.81-option6-ntp-server-suboption.patch +# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;h=3052ce208acf602f0163166dcefb7330d537cedb +Patch37: dnsmasq-2.81-linux-SIOCGSTAMP.patch +# Downstream only patch; fixes Patch34 change +Patch38: dnsmasq-2.79-server-domain-fixup.patch # This is workaround to nettle bug #1549190 # https://bugzilla.redhat.com/show_bug.cgi?id=1549190 @@ -140,6 +147,10 @@ server's leases. %patch32 -p1 -b .rh1998448 %patch33 -p1 -b .dhcpv6-client-arch %patch34 -p1 -b .rh1919894 +%patch35 -p1 -b .CVE-2022-0934 +%patch36 -p1 -b .rh2049691 +%patch37 -p1 -b .SIOCGSTAMP +%patch38 -p1 -b .rh2120357 # use /var/lib/dnsmasq instead of /var/lib/misc for file in dnsmasq.conf.example man/dnsmasq.8 man/es/dnsmasq.8 src/config.h; do @@ -239,6 +250,15 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf %{_mandir}/man1/dhcp_* %changelog +* Mon Aug 22 2022 Petr Menšík - 2.79-24 +- Prevent endless loop in forward_query (#2120357) + +* Thu May 12 2022 Petr Menšík - 2.79-23 +- Add IPv6 ntp-server suboptions support (#2049691) + +* Fri Mar 25 2022 Petr Menšík - 2.79-22 +- Prevent use after free in dhcp6_no_relay (CVE-2022-0934) + * Thu Jan 27 2022 Petr Menšík - 2.79-21 - Send queries only to best domain-specific server (#1919894)