diff --git a/SOURCES/dnsmasq-2.81-dhcpv6-relay-link-address.patch b/SOURCES/dnsmasq-2.81-dhcpv6-relay-link-address.patch new file mode 100644 index 0000000..95bbe2d --- /dev/null +++ b/SOURCES/dnsmasq-2.81-dhcpv6-relay-link-address.patch @@ -0,0 +1,56 @@ +From f8c77edbdffb8ada7753ea9fa104f0f6da70cfe3 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Thu, 10 Jan 2019 21:58:18 +0000 +Subject: [PATCH] Fix removal of DHCP_CLIENT_MAC options from DHCPv6 relay + replies. + +--- + src/rfc3315.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index d3c1722..79b2a86 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -219,21 +219,25 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, + if (opt6_ptr(opt, 0) + opt6_len(opt) > end) + return 0; + +- int o = new_opt6(opt6_type(opt)); +- if (opt6_type(opt) == OPTION6_RELAY_MSG) ++ /* Don't copy MAC address into reply. */ ++ if (opt6_type(opt) != OPTION6_CLIENT_MAC) + { +- struct in6_addr align; +- /* the packet data is unaligned, copy to aligned storage */ +- memcpy(&align, inbuff + 2, IN6ADDRSZ); +- state->link_address = &align; +- /* zero is_unicast since that is now known to refer to the +- relayed packet, not the original sent by the client */ +- if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now)) +- return 0; ++ int o = new_opt6(opt6_type(opt)); ++ if (opt6_type(opt) == OPTION6_RELAY_MSG) ++ { ++ struct in6_addr align; ++ /* the packet data is unaligned, copy to aligned storage */ ++ memcpy(&align, inbuff + 2, IN6ADDRSZ); ++ state->link_address = &align; ++ /* zero is_unicast since that is now known to refer to the ++ relayed packet, not the original sent by the client */ ++ if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now)) ++ return 0; ++ } ++ else ++ put_opt6(opt6_ptr(opt, 0), opt6_len(opt)); ++ end_opt6(o); + } +- else if (opt6_type(opt) != OPTION6_CLIENT_MAC) +- put_opt6(opt6_ptr(opt, 0), opt6_len(opt)); +- end_opt6(o); + } + + return 1; +-- +2.39.1 + diff --git a/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch b/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch index afc36bb..4624cc3 100644 --- a/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch +++ b/SOURCES/dnsmasq-2.87-CVE-2022-0934.patch @@ -1,175 +1,172 @@ -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 +From 471cd540e755d2a5e92b4e8cd2ab2027beaba449 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Thu, 31 Mar 2022 21:35:20 +0100 +Subject: [PATCH] Fix write-after-free error in DHCPv6 code. CVE-2022-0934 + refers. -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(-) + src/rfc3315.c | 48 +++++++++++++++++++++++++++--------------------- + 1 file changed, 27 insertions(+), 21 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); +diff --git a/src/rfc3315.c b/src/rfc3315.c +index 554b1fe..bc77fbf 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -36,9 +36,9 @@ struct state { #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)); +-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, ++static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz, + struct in6_addr *client_addr, int is_unicast, time_t now); +-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now); ++static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now); + static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts); + static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string); + static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string); +@@ -110,12 +110,12 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if } -+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, + /* This cost me blood to write, it will probably cost you blood to understand - srk. */ +-static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, ++static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz, + struct in6_addr *client_addr, int is_unicast, time_t now) + { void *end = inbuff + sz; void *opts = inbuff + 34; - int msg_type = *((unsigned char *)inbuff); -- unsigned char *outmsgtypep; +- int msg_type = *((unsigned char *)inbuff); ++ int msg_type = *inbuff; + unsigned char *outmsgtypep; void *opt; struct dhcp_vendor *vendor; +@@ -241,15 +241,15 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, + return 1; + } -@@ -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_ +-static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now) ++static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now) + { + void *opt; +- int i, o, o1, start_opts; ++ int i, o, o1, start_opts, start_msg; + struct dhcp_opt *opt_cfg; struct dhcp_netid *tagif; struct dhcp_config *config = NULL; struct dhcp_netid known_id, iface_id, v6_id; - unsigned char *outmsgtypep; -+ unsigned char *xid; ++ unsigned char outmsgtype; 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_ +@@ -285,12 +285,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + v6_id.next = state->tags; state->tags = &v6_id; - /* copy over transaction-id, and save pointer to message type */ +- /* copy over transaction-id, and save pointer to message type */ - if (!(outmsgtypep = put_opt6(inbuff, 4))) -+ if (!(xid = put_opt6(inbuff, 4))) ++ start_msg = save_counter(-1); ++ /* copy over transaction-id */ ++ if (!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; - +- ++ state->xid = inbuff[3] | inbuff[2] << 8 | inbuff[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_ + for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current) +@@ -336,7 +337,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); ++ outmsgtype = 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_ +@@ -600,11 +601,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); ++ outmsgtype = DHCP6ADVERTISE; if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0)) { - *outmsgtypep = DHCP6REPLY; -+ put_msgtype6(DHCP6REPLY); ++ outmsgtype = 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_ +@@ -876,7 +877,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); ++ outmsgtype = 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_ +@@ -992,7 +993,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); ++ outmsgtype = 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_ +@@ -1104,7 +1105,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); ++ outmsgtype = 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_ +@@ -1168,7 +1169,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); ++ outmsgtype = 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_ +@@ -1177,7 +1178,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); ++ outmsgtype = 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_ +@@ -1242,7 +1243,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); ++ outmsgtype = DHCP6REPLY; log6_quiet(state, "DHCPDECLINE", NULL, NULL); +@@ -1321,7 +1322,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_ + } + + } +- ++ ++ /* Fill in the message type. Note that we store the offset, ++ not a direct pointer, since the packet memory may have been ++ reallocated. */ ++ ((unsigned char *)(daemon->outpacket.iov_base))[start_msg] = outmsgtype; ++ + log_tags(tagif, state->xid); + log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1)); + -- -2.34.1 +2.39.1 diff --git a/SPECS/dnsmasq.spec b/SPECS/dnsmasq.spec index 7d91171..86ef2da 100644 --- a/SPECS/dnsmasq.spec +++ b/SPECS/dnsmasq.spec @@ -13,7 +13,7 @@ Name: dnsmasq Version: 2.79 -Release: 24%{?extraversion:.%{extraversion}}%{?dist} +Release: 24%{?extraversion:.%{extraversion}}%{?dist}.1 Summary: A lightweight DHCP/caching DNS server License: GPLv2 or GPLv3 @@ -73,6 +73,7 @@ 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 +# http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=03345ecefeb0d82e3c3a4c28f27c3554f0611b39 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 @@ -80,6 +81,8 @@ Patch36: dnsmasq-2.81-option6-ntp-server-suboption.patch Patch37: dnsmasq-2.81-linux-SIOCGSTAMP.patch # Downstream only patch; fixes Patch34 change Patch38: dnsmasq-2.79-server-domain-fixup.patch +# https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;h=f8c77edbdffb8ada7753ea9fa104f0f6da70cfe3 +Patch39: dnsmasq-2.81-dhcpv6-relay-link-address.patch # This is workaround to nettle bug #1549190 # https://bugzilla.redhat.com/show_bug.cgi?id=1549190 @@ -151,6 +154,7 @@ server's leases. %patch36 -p1 -b .rh2049691 %patch37 -p1 -b .SIOCGSTAMP %patch38 -p1 -b .rh2120357 +%patch39 -p1 -b .rh2169355 # 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 @@ -250,6 +254,10 @@ install -Dpm 644 %{SOURCE2} %{buildroot}%{_sysusersdir}/dnsmasq.conf %{_mandir}/man1/dhcp_* %changelog +* Wed Feb 15 2023 Petr Menšík - 2.79-24.1 +- Avoid DHCPv6 relayed replies with Client Link-Layer Address (#2169355) +- Use upstream change for CVE-2022-0934 (#2164859) + * Mon Aug 22 2022 Petr Menšík - 2.79-24 - Prevent endless loop in forward_query (#2120357)