Send connman mailing list submissions to
        connman@lists.01.org

To subscribe or unsubscribe via email, send a message with subject or
body 'help' to
        connman-requ...@lists.01.org

You can reach the person managing the list at
        connman-ow...@lists.01.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of connman digest..."

Today's Topics:

   1. [PATCH 0/3] dnsproxy fixes (Daniel Wagner)
   2. [PATCH 3/3] dnsproxy: Add length checks to prevent buffer overflow
      (Daniel Wagner)
   3. [PATCH 1/3] gdhcp: Avoid reading invalid data in dhcp_get_option
      (Daniel Wagner)
   4. [PATCH 2/3] gdhcp: Avoid leaking stack data via unitiialized variable
      (Daniel Wagner)
   5. Re: [PATCH 0/3] dnsproxy fixes (Daniel Wagner)


----------------------------------------------------------------------

Date: Mon,  8 Feb 2021 10:00:45 +0100
From: Daniel Wagner <w...@monom.org>
Subject: [PATCH 0/3] dnsproxy fixes
To: connman@lists.01.org
Cc: Daniel Wagner <w...@monom.org>
Message-ID: <20210208090048.6063-1-w...@monom.org>

Important fixes for the dnsproxy provided by Tesla.

Fixes: CVE-2021-26675
Fixes: CVE-2021-26676

Colin Wee (3):
  gdhcp: Avoid reading invalid data in dhcp_get_option
  gdhcp: Avoid leaking stack data via unitiialized variable
  dnsproxy: Add length checks to prevent buffer overflow

 gdhcp/client.c | 22 ++++++++++++----------
 gdhcp/common.c | 24 +++++++++++++++++++-----
 gdhcp/common.h |  2 +-
 gdhcp/server.c | 12 +++++++-----
 src/dnsproxy.c | 14 +++++++++++---
 5 files changed, 50 insertions(+), 24 deletions(-)

-- 
2.30.0

------------------------------

Date: Mon,  8 Feb 2021 10:00:48 +0100
From: Daniel Wagner <w...@monom.org>
Subject: [PATCH 3/3] dnsproxy: Add length checks to prevent buffer
        overflow
To: connman@lists.01.org
Cc: Colin Wee <c...@tesla.com>
Message-ID: <20210208090048.6063-4-w...@monom.org>

From: Colin Wee <c...@tesla.com>

Fixes: CVE-2021-26675
---
 src/dnsproxy.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index a7bf87a14435..4f5c897f75d9 100644
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -1767,6 +1767,7 @@ static char *uncompress(int16_t field_count, char *start, 
char *end,
                        char **uncompressed_ptr)
 {
        char *uptr = *uncompressed_ptr; /* position in result buffer */
+       char * const uncomp_end = uncompressed + uncomp_len - 1;
 
        debug("count %d ptr %p end %p uptr %p", field_count, ptr, end, uptr);
 
@@ -1787,12 +1788,15 @@ static char *uncompress(int16_t field_count, char 
*start, char *end,
                 * tmp buffer.
                 */
 
-               ulen = strlen(name);
-               strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
-
                debug("pos %d ulen %d left %d name %s", pos, ulen,
                        (int)(uncomp_len - (uptr - uncompressed)), uptr);
 
+               ulen = strlen(name);
+               if ((uptr + ulen + 1) > uncomp_end) {
+                       goto out;
+               }
+               strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
+
                uptr += ulen;
                *uptr++ = '\0';
 
@@ -1802,6 +1806,10 @@ static char *uncompress(int16_t field_count, char 
*start, char *end,
                 * We copy also the fixed portion of the result (type, class,
                 * ttl, address length and the address)
                 */
+               if ((uptr + NS_RRFIXEDSZ) > uncomp_end) {
+                       debug("uncompressed data too large for buffer");
+                       goto out;
+               }
                memcpy(uptr, ptr, NS_RRFIXEDSZ);
 
                dns_type = uptr[0] << 8 | uptr[1];
-- 
2.30.0

------------------------------

Date: Mon,  8 Feb 2021 10:00:46 +0100
From: Daniel Wagner <w...@monom.org>
Subject: [PATCH 1/3] gdhcp: Avoid reading invalid data in
        dhcp_get_option
To: connman@lists.01.org
Cc: Colin Wee <c...@tesla.com>
Message-ID: <20210208090048.6063-2-w...@monom.org>

From: Colin Wee <c...@tesla.com>

---
 gdhcp/client.c | 20 +++++++++++---------
 gdhcp/common.c | 24 +++++++++++++++++++-----
 gdhcp/common.h |  2 +-
 gdhcp/server.c | 12 +++++++-----
 4 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/gdhcp/client.c b/gdhcp/client.c
index 09dfe5ec2991..6a5613e7d5aa 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -1629,12 +1629,12 @@ static void start_request(GDHCPClient *dhcp_client)
                                                        NULL);
 }
 
-static uint32_t get_lease(struct dhcp_packet *packet)
+static uint32_t get_lease(struct dhcp_packet *packet, uint16_t packet_len)
 {
        uint8_t *option;
        uint32_t lease_seconds;
 
-       option = dhcp_get_option(packet, DHCP_LEASE_TIME);
+       option = dhcp_get_option(packet, packet_len, DHCP_LEASE_TIME);
        if (!option)
                return 3600;
 
@@ -2226,7 +2226,8 @@ static void get_dhcpv6_request(GDHCPClient *dhcp_client,
        }
 }
 
-static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet)
+static void get_request(GDHCPClient *dhcp_client, struct dhcp_packet *packet,
+               uint16_t packet_len)
 {
        GDHCPOptionType type;
        GList *list, *value_list;
@@ -2237,7 +2238,7 @@ static void get_request(GDHCPClient *dhcp_client, struct 
dhcp_packet *packet)
        for (list = dhcp_client->request_list; list; list = list->next) {
                code = (uint8_t) GPOINTER_TO_INT(list->data);
 
-               option = dhcp_get_option(packet, code);
+               option = dhcp_get_option(packet, packet_len, code);
                if (!option) {
                        g_hash_table_remove(dhcp_client->code_value_hash,
                                                GINT_TO_POINTER((int) code));
@@ -2297,6 +2298,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                re = dhcp_recv_l2_packet(&packet,
                                        dhcp_client->listener_sockfd,
                                        &dst_addr);
+               pkt_len = (uint16_t)(unsigned int)re;
                xid = packet.xid;
        } else if (dhcp_client->listen_mode == L3) {
                if (dhcp_client->type == G_DHCP_IPV6) {
@@ -2361,7 +2363,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                        dhcp_client->status_code = status;
                }
        } else {
-               message_type = dhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
+               message_type = dhcp_get_option(&packet, pkt_len, 
DHCP_MESSAGE_TYPE);
                if (!message_type)
                        return TRUE;
        }
@@ -2378,7 +2380,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                dhcp_client->timeout = 0;
                dhcp_client->retry_times = 0;
 
-               option = dhcp_get_option(&packet, DHCP_SERVER_ID);
+               option = dhcp_get_option(&packet, pkt_len, DHCP_SERVER_ID);
                dhcp_client->server_ip = get_be32(option);
                dhcp_client->requested_ip = ntohl(packet.yiaddr);
 
@@ -2428,9 +2430,9 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
 
                        remove_timeouts(dhcp_client);
 
-                       dhcp_client->lease_seconds = get_lease(&packet);
+                       dhcp_client->lease_seconds = get_lease(&packet, 
pkt_len);
 
-                       get_request(dhcp_client, &packet);
+                       get_request(dhcp_client, &packet, pkt_len);
 
                        switch_listening_mode(dhcp_client, L_NONE);
 
@@ -2438,7 +2440,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                        dhcp_client->assigned_ip = get_ip(packet.yiaddr);
 
                        if (dhcp_client->state == REBOOTING) {
-                               option = dhcp_get_option(&packet,
+                               option = dhcp_get_option(&packet, pkt_len,
                                                        DHCP_SERVER_ID);
                                dhcp_client->server_ip = get_be32(option);
                        }
diff --git a/gdhcp/common.c b/gdhcp/common.c
index 1d667d17308f..c8916aa81666 100644
--- a/gdhcp/common.c
+++ b/gdhcp/common.c
@@ -73,18 +73,21 @@ GDHCPOptionType dhcp_get_code_type(uint8_t code)
        return OPTION_UNKNOWN;
 }
 
-uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code)
+uint8_t *dhcp_get_option(struct dhcp_packet *packet, uint16_t packet_len, int 
code)
 {
        int len, rem;
-       uint8_t *optionptr;
+       uint8_t *optionptr, *options_end;
+       size_t options_len;
        uint8_t overload = 0;
 
        /* option bytes: [code][len][data1][data2]..[dataLEN] */
        optionptr = packet->options;
        rem = sizeof(packet->options);
+       options_len = packet_len - (sizeof(*packet) - sizeof(packet->options));
+       options_end = optionptr + options_len - 1;
 
        while (1) {
-               if (rem <= 0)
+               if ((rem <= 0) && (optionptr + OPT_CODE > options_end))
                        /* Bad packet, malformed option field */
                        return NULL;
 
@@ -115,14 +118,25 @@ uint8_t *dhcp_get_option(struct dhcp_packet *packet, int 
code)
                        break;
                }
 
+               if (optionptr + OPT_LEN > options_end) {
+                       /* bad packet, would read length field from OOB */
+                       return NULL;
+               }
+
                len = 2 + optionptr[OPT_LEN];
 
                rem -= len;
                if (rem < 0)
                        continue; /* complain and return NULL */
 
-               if (optionptr[OPT_CODE] == code)
-                       return optionptr + OPT_DATA;
+               if (optionptr[OPT_CODE] == code) {
+                       if (optionptr + len > options_end) {
+                               /* bad packet, option length points OOB */
+                               return NULL;
+                       } else {
+                               return optionptr + OPT_DATA;
+                       }
+               }
 
                if (optionptr[OPT_CODE] == DHCP_OPTION_OVERLOAD)
                        overload |= optionptr[OPT_DATA];
diff --git a/gdhcp/common.h b/gdhcp/common.h
index 9660231cc49d..8f63fd755623 100644
--- a/gdhcp/common.h
+++ b/gdhcp/common.h
@@ -179,7 +179,7 @@ struct in6_pktinfo {
 };
 #endif
 
-uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code);
+uint8_t *dhcp_get_option(struct dhcp_packet *packet, uint16_t packet_len, int 
code);
 uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len,
                        int code, uint16_t *option_len, int *option_count);
 uint8_t *dhcpv6_get_sub_option(unsigned char *option, uint16_t max_len,
diff --git a/gdhcp/server.c b/gdhcp/server.c
index 85405f193fe3..52ea2a55b230 100644
--- a/gdhcp/server.c
+++ b/gdhcp/server.c
@@ -413,7 +413,7 @@ GDHCPServer *g_dhcp_server_new(GDHCPType type,
 }
 
 
-static uint8_t check_packet_type(struct dhcp_packet *packet)
+static uint8_t check_packet_type(struct dhcp_packet *packet, uint16_t 
packet_len)
 {
        uint8_t *type;
 
@@ -423,7 +423,7 @@ static uint8_t check_packet_type(struct dhcp_packet *packet)
        if (packet->op != BOOTREQUEST)
                return 0;
 
-       type = dhcp_get_option(packet, DHCP_MESSAGE_TYPE);
+       type = dhcp_get_option(packet, packet_len, DHCP_MESSAGE_TYPE);
 
        if (!type)
                return 0;
@@ -651,6 +651,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
        struct dhcp_lease *lease;
        uint32_t requested_nip = 0;
        uint8_t type, *server_id_option, *request_ip_option;
+       uint16_t packet_len;
        int re;
 
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
@@ -661,12 +662,13 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
        re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd);
        if (re < 0)
                return TRUE;
+       packet_len = (uint16_t)(unsigned int)re;
 
-       type = check_packet_type(&packet);
+       type = check_packet_type(&packet, packet_len);
        if (type == 0)
                return TRUE;
 
-       server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
+       server_id_option = dhcp_get_option(&packet, packet_len, DHCP_SERVER_ID);
        if (server_id_option) {
                uint32_t server_nid =
                        get_unaligned((const uint32_t *) server_id_option);
@@ -675,7 +677,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
                        return TRUE;
        }
 
-       request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
+       request_ip_option = dhcp_get_option(&packet, packet_len, 
DHCP_REQUESTED_IP);
        if (request_ip_option)
                requested_nip = get_be32(request_ip_option);
 
-- 
2.30.0

------------------------------

Date: Mon,  8 Feb 2021 10:00:47 +0100
From: Daniel Wagner <w...@monom.org>
Subject: [PATCH 2/3] gdhcp: Avoid leaking stack data via unitiialized
        variable
To: connman@lists.01.org
Cc: Colin Wee <c...@tesla.com>
Message-ID: <20210208090048.6063-3-w...@monom.org>

From: Colin Wee <c...@tesla.com>

Fixes: CVE-2021-26676
---
 gdhcp/client.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdhcp/client.c b/gdhcp/client.c
index 6a5613e7d5aa..c7b85e58e2be 100644
--- a/gdhcp/client.c
+++ b/gdhcp/client.c
@@ -2270,7 +2270,7 @@ static gboolean listener_event(GIOChannel *channel, 
GIOCondition condition,
 {
        GDHCPClient *dhcp_client = user_data;
        struct sockaddr_in dst_addr = { 0 };
-       struct dhcp_packet packet;
+       struct dhcp_packet packet = { 0 };
        struct dhcpv6_packet *packet6 = NULL;
        uint8_t *message_type = NULL, *client_id = NULL, *option,
                *server_id = NULL;
-- 
2.30.0

------------------------------

Date: Mon, 8 Feb 2021 10:02:02 +0100
From: Daniel Wagner <w...@monom.org>
Subject: Re: [PATCH 0/3] dnsproxy fixes
To: connman@lists.01.org
Message-ID: <bde8d813-5819-9f97-e908-53315620f...@monom.org>
Content-Type: text/plain; charset=utf-8; format=flowed

On 08.02.21 10:00, Daniel Wagner wrote:
> Important fixes for the dnsproxy provided by Tesla.
> 
> Fixes: CVE-2021-26675
> Fixes: CVE-2021-26676

Patches applied.

------------------------------

Subject: Digest Footer

_______________________________________________
connman mailing list -- connman@lists.01.org
To unsubscribe send an email to connman-le...@lists.01.org


------------------------------

End of connman Digest, Vol 64, Issue 9
**************************************

Reply via email to