Blame SOURCES/dnsmasq-2.87-CVE-2022-0934.patch

e7c5f6
From b0cb924292daecc1cc89fbd3911373eb468fc8f1 Mon Sep 17 00:00:00 2001
e7c5f6
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
e7c5f6
Date: Tue, 22 Feb 2022 00:45:01 +0100
e7c5f6
Subject: [PATCH] Change message type by dedicated function
e7c5f6
e7c5f6
Long-term pointer to beginning of message does not work well. I case
e7c5f6
outpacket is reallocated in any new_opt6() section, original outmsgtypep
e7c5f6
pointer becomes invalid. Instead of using that pointer use dedicated
e7c5f6
function, which will change just the first byte of the message.
e7c5f6
e7c5f6
This makes sure correct beginning of packet is always used.
e7c5f6
---
e7c5f6
 src/dnsmasq.h   |  1 +
e7c5f6
 src/outpacket.c | 11 +++++++++++
e7c5f6
 src/rfc3315.c   | 29 ++++++++++++++---------------
e7c5f6
 3 files changed, 26 insertions(+), 15 deletions(-)
e7c5f6
e7c5f6
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
e7c5f6
index 27ff86a..0749260 100644
e7c5f6
--- a/src/dnsmasq.h
e7c5f6
+++ b/src/dnsmasq.h
e7c5f6
@@ -1563,6 +1563,7 @@ void put_opt6_long(unsigned int val);
e7c5f6
 void put_opt6_short(unsigned int val);
e7c5f6
 void put_opt6_char(unsigned int val);
e7c5f6
 void put_opt6_string(char *s);
e7c5f6
+void put_msgtype6(unsigned int val);
e7c5f6
 #endif
e7c5f6
 
e7c5f6
 /* radv.c */
e7c5f6
diff --git a/src/outpacket.c b/src/outpacket.c
e7c5f6
index d20bd33..1c8f1bc 100644
e7c5f6
--- a/src/outpacket.c
e7c5f6
+++ b/src/outpacket.c
e7c5f6
@@ -115,4 +115,15 @@ void put_opt6_string(char *s)
e7c5f6
   put_opt6(s, strlen(s));
e7c5f6
 }
e7c5f6
 
e7c5f6
+void put_msgtype6(unsigned int val)
e7c5f6
+{
e7c5f6
+  if (outpacket_counter == 0)
e7c5f6
+    put_opt6_char(val);
e7c5f6
+  else
e7c5f6
+    {
e7c5f6
+      unsigned char *p = daemon->outpacket.iov_base;
e7c5f6
+      *p = val;
e7c5f6
+    }
e7c5f6
+}
e7c5f6
+
e7c5f6
 #endif
e7c5f6
diff --git a/src/rfc3315.c b/src/rfc3315.c
e7c5f6
index 554b1fe..1f1aad8 100644
e7c5f6
--- a/src/rfc3315.c
e7c5f6
+++ b/src/rfc3315.c
e7c5f6
@@ -116,7 +116,6 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
e7c5f6
   void *end = inbuff + sz;
e7c5f6
   void *opts = inbuff + 34;
e7c5f6
   int msg_type = *((unsigned char *)inbuff);
e7c5f6
-  unsigned char *outmsgtypep;
e7c5f6
   void *opt;
e7c5f6
   struct dhcp_vendor *vendor;
e7c5f6
 
e7c5f6
@@ -178,9 +177,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
e7c5f6
     return 0;
e7c5f6
   
e7c5f6
   /* copy header stuff into reply message and set type to reply */
e7c5f6
-  if (!(outmsgtypep = put_opt6(inbuff, 34)))
e7c5f6
+  if (!put_opt6(inbuff, 34))
e7c5f6
     return 0;
e7c5f6
-  *outmsgtypep = DHCP6RELAYREPL;
e7c5f6
+  put_msgtype6(DHCP6RELAYREPL);
e7c5f6
 
e7c5f6
   /* look for relay options and set tags if found. */
e7c5f6
   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
e7c5f6
@@ -249,7 +248,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
   struct dhcp_netid *tagif;
e7c5f6
   struct dhcp_config *config = NULL;
e7c5f6
   struct dhcp_netid known_id, iface_id, v6_id;
e7c5f6
-  unsigned char *outmsgtypep;
e7c5f6
+  unsigned char *xid;
e7c5f6
   struct dhcp_vendor *vendor;
e7c5f6
   struct dhcp_context *context_tmp;
e7c5f6
   struct dhcp_mac *mac_opt;
e7c5f6
@@ -286,10 +285,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
   state->tags = &v6_id;
e7c5f6
 
e7c5f6
   /* copy over transaction-id, and save pointer to message type */
e7c5f6
-  if (!(outmsgtypep = put_opt6(inbuff, 4)))
e7c5f6
+  if (!(xid = put_opt6(inbuff, 4)))
e7c5f6
     return 0;
e7c5f6
   start_opts = save_counter(-1);
e7c5f6
-  state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
e7c5f6
+  state->xid = xid[3] | xid[2] << 8 | xid[1] << 16;
e7c5f6
    
e7c5f6
   /* We're going to be linking tags from all context we use. 
e7c5f6
      mark them as unused so we don't link one twice and break the list */
e7c5f6
@@ -336,7 +335,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
       (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
e7c5f6
     
e7c5f6
     {  
e7c5f6
-      *outmsgtypep = DHCP6REPLY;
e7c5f6
+      put_msgtype6(DHCP6REPLY);
e7c5f6
       o1 = new_opt6(OPTION6_STATUS_CODE);
e7c5f6
       put_opt6_short(DHCP6USEMULTI);
e7c5f6
       put_opt6_string("Use multicast");
e7c5f6
@@ -600,11 +599,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
 	struct dhcp_netid *solicit_tags;
e7c5f6
 	struct dhcp_context *c;
e7c5f6
 	
e7c5f6
-	*outmsgtypep = DHCP6ADVERTISE;
e7c5f6
+	put_msgtype6(DHCP6ADVERTISE);
e7c5f6
 	
e7c5f6
 	if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
e7c5f6
 	  {
e7c5f6
-	    *outmsgtypep = DHCP6REPLY;
e7c5f6
+	    put_msgtype6(DHCP6REPLY);
e7c5f6
 	    state->lease_allocate = 1;
e7c5f6
 	    o = new_opt6(OPTION6_RAPID_COMMIT);
e7c5f6
 	    end_opt6(o);
e7c5f6
@@ -876,7 +875,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
 	int start = save_counter(-1);
e7c5f6
 
e7c5f6
 	/* set reply message type */
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 	state->lease_allocate = 1;
e7c5f6
 
e7c5f6
 	log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
e7c5f6
@@ -992,7 +991,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
     case DHCP6RENEW:
e7c5f6
       {
e7c5f6
 	/* set reply message type */
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 	
e7c5f6
 	log6_quiet(state, "DHCPRENEW", NULL, NULL);
e7c5f6
 
e7c5f6
@@ -1104,7 +1103,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
 	int good_addr = 0;
e7c5f6
 
e7c5f6
 	/* set reply message type */
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 	
e7c5f6
 	log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
e7c5f6
 	
e7c5f6
@@ -1168,7 +1167,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
 	log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
e7c5f6
 	if (ignore)
e7c5f6
 	  return 0;
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 	tagif = add_options(state, 1);
e7c5f6
 	break;
e7c5f6
       }
e7c5f6
@@ -1177,7 +1176,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
     case DHCP6RELEASE:
e7c5f6
       {
e7c5f6
 	/* set reply message type */
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 
e7c5f6
 	log6_quiet(state, "DHCPRELEASE", NULL, NULL);
e7c5f6
 
e7c5f6
@@ -1242,7 +1241,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
e7c5f6
     case DHCP6DECLINE:
e7c5f6
       {
e7c5f6
 	/* set reply message type */
e7c5f6
-	*outmsgtypep = DHCP6REPLY;
e7c5f6
+	put_msgtype6(DHCP6REPLY);
e7c5f6
 	
e7c5f6
 	log6_quiet(state, "DHCPDECLINE", NULL, NULL);
e7c5f6
 
e7c5f6
-- 
e7c5f6
2.34.1
e7c5f6