From e7c5f66cf542f517b803afc0a772196226ffee4d Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 27 2022 10:58:42 +0000 Subject: import dnsmasq-2.85-4.el9 --- 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 b39f215..be042ca 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -20,7 +20,7 @@ Name: dnsmasq Version: 2.85 -Release: 3%{?extraversion:.%{extraversion}}%{?dist} +Release: 4%{?extraversion:.%{extraversion}}%{?dist} Summary: A lightweight DHCP/caching DNS server License: GPLv2 or GPLv3 @@ -47,6 +47,7 @@ Patch4: dnsmasq-2.79-server-domain-rh1919894.patch # https://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2021q3/015640.html Patch5: dnsmasq-2.86-alternative-lease.patch Patch6: dnsmasq-2.86-dhcpv6-client-arch.patch +Patch7: dnsmasq-2.87-CVE-2022-0934.patch # This is workaround to nettle bug #1549190 # https://bugzilla.redhat.com/show_bug.cgi?id=1549190 @@ -190,6 +191,9 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/%{name}.conf %{_mandir}/man1/dhcp_* %changelog +* Fri Mar 25 2022 Petr Menšík - 2.85-4 +- Prevent use after free in dhcp6_no_relay (CVE-2022-0934) + * Thu Jan 27 2022 Petr Menšík - 2.85-3 - Send queries only to best domain-specific server (#2047510) - Offer alternate DHCPv6 address if requested is already leased (#1998448)