git: 03b5b25346d3 - main - dns/dnsmasq: fix CVE-2022-0934 DHCPv6 vuln

From: Matthias Andree <mandree_at_FreeBSD.org>
Date: Sun, 03 Apr 2022 11:16:13 UTC
The branch main has been updated by mandree:

URL: https://cgit.FreeBSD.org/ports/commit/?id=03b5b25346d359e29c16da94772d41637320bdf2

commit 03b5b25346d359e29c16da94772d41637320bdf2
Author:     Matthias Andree <mandree@FreeBSD.org>
AuthorDate: 2022-04-03 11:07:52 +0000
Commit:     Matthias Andree <mandree@FreeBSD.org>
CommitDate: 2022-04-03 11:15:58 +0000

    dns/dnsmasq: fix CVE-2022-0934 DHCPv6 vuln
    
    Security:       3f321a5a-b33b-11ec-80c2-1bb2c6a00592
    Security:       CVE-2022-0934
    MFH:            2022Q2
---
 dns/dnsmasq/Makefile                  |   2 +-
 dns/dnsmasq/files/patch-CVE-2022-0934 | 175 ++++++++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+), 1 deletion(-)

diff --git a/dns/dnsmasq/Makefile b/dns/dnsmasq/Makefile
index 19958b46de17..87fd6f3e2f5a 100644
--- a/dns/dnsmasq/Makefile
+++ b/dns/dnsmasq/Makefile
@@ -3,7 +3,7 @@
 PORTNAME=	dnsmasq
 DISTVERSION=	2.86
 # Leave the PORTREVISION in even if 0 to avoid accidental PORTEPOCH bumps:
-PORTREVISION=	3
+PORTREVISION=	4
 PORTEPOCH=	1
 CATEGORIES=	dns
 MASTER_SITES=	https://www.thekelleys.org.uk/dnsmasq/ \
diff --git a/dns/dnsmasq/files/patch-CVE-2022-0934 b/dns/dnsmasq/files/patch-CVE-2022-0934
new file mode 100644
index 000000000000..c063e15b2e34
--- /dev/null
+++ b/dns/dnsmasq/files/patch-CVE-2022-0934
@@ -0,0 +1,175 @@
+From dcc62a514092c8afeab4e502db9e65f03c2e1d47 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+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 51a1aa6..c1c75c1 100644
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -1736,6 +1736,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 abb3a3a..f322811 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 cee8382..baeb51e 100644
+--- a/src/rfc3315.c
++++ b/src/rfc3315.c
+@@ -110,7 +110,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;
+ 
+@@ -192,9 +191,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)
+@@ -267,7 +266,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;
+@@ -297,10 +296,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 */
+@@ -347,7 +346,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");
+@@ -619,11 +618,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);
+@@ -809,7 +808,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);
+@@ -924,7 +923,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
+ 	int address_assigned = 0;
+ 
+ 	/* set reply message type */
+-	*outmsgtypep = DHCP6REPLY;
++	put_msgtype6(DHCP6REPLY);
+ 	
+ 	log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
+ 
+@@ -1057,7 +1056,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);
+ 	
+@@ -1121,7 +1120,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;
+       }
+@@ -1130,7 +1129,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);
+ 
+@@ -1195,7 +1194,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
+