nuttx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From xiaoxi...@apache.org
Subject [incubator-nuttx-apps] branch master updated: dhcpc: fix potential invalid memory reads
Date Wed, 30 Jun 2021 08:00:50 GMT
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 7fdd751  dhcpc: fix potential invalid memory reads
7fdd751 is described below

commit 7fdd751b7a8444be69f5583e8ffa3874b28c534e
Author: Beat K√ľng <beat-kueng@gmx.net>
AuthorDate: Tue Jun 29 13:39:16 2021 +0200

    dhcpc: fix potential invalid memory reads
    
    - check for minimum packet length (44 bytes, which includes the fields we
      read next)
    - pass the correct remaining buffer length to dhcpc_parseoptions()
    - dhcpc_parseoptions(): ensure we never read past the end of the buffer
---
 netutils/dhcpc/dhcpc.c | 74 +++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 61 insertions(+), 13 deletions(-)

diff --git a/netutils/dhcpc/dhcpc.c b/netutils/dhcpc/dhcpc.c
index 4a6d091..372ee23 100644
--- a/netutils/dhcpc/dhcpc.c
+++ b/netutils/dhcpc/dhcpc.c
@@ -326,52 +326,98 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,
 
             /* Get subnet mask in network order */
 
-            memcpy(&presult->netmask.s_addr, optptr + 2, 4);
+            if (optptr + 6 <= end)
+              {
+                memcpy(&presult->netmask.s_addr, optptr + 2, 4);
+              }
+            else
+              {
+                nerr("Packet too short (netmask missing)\n");
+              }
             break;
 
           case DHCP_OPTION_ROUTER:
 
             /* Get the default router address in network order */
 
-            memcpy(&presult->default_router.s_addr, optptr + 2, 4);
+            if (optptr + 6 <= end)
+              {
+                memcpy(&presult->default_router.s_addr, optptr + 2, 4);
+              }
+            else
+              {
+                nerr("Packet too short (router address missing)\n");
+              }
             break;
 
           case DHCP_OPTION_DNS_SERVER:
 
             /* Get the DNS server address in network order */
 
-            memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4);
+            if (optptr + 6 <= end)
+              {
+                memcpy(&presult->dnsaddr.s_addr, optptr + 2, 4);
+              }
+            else
+              {
+                nerr("Packet too short (DNS address missing)\n");
+              }
             break;
 
           case DHCP_OPTION_MSG_TYPE:
 
             /* Get message type */
 
-            type = *(optptr + 2);
+            if (optptr + 3 <= end)
+              {
+                type = *(optptr + 2);
+              }
+            else
+              {
+                nerr("Packet too short (type missing)\n");
+              }
             break;
 
           case DHCP_OPTION_SERVER_ID:
 
             /* Get server address in network order */
 
-            memcpy(&presult->serverid.s_addr, optptr + 2, 4);
+            if (optptr + 6 <= end)
+              {
+                memcpy(&presult->serverid.s_addr, optptr + 2, 4);
+              }
+            else
+              {
+                nerr("Packet too short (server address missing)\n");
+              }
             break;
 
           case DHCP_OPTION_LEASE_TIME:
-            {
+
               /* Get lease time (in seconds) in host order */
 
-              uint16_t tmp[2];
-              memcpy(tmp, optptr + 2, 4);
-              presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 |
-                                     (uint32_t)ntohs(tmp[1]);
-            }
+            if (optptr + 6 <= end)
+              {
+                uint16_t tmp[2];
+                memcpy(tmp, optptr + 2, 4);
+                presult->lease_time = ((uint32_t)ntohs(tmp[0])) << 16 |
+                                       (uint32_t)ntohs(tmp[1]);
+              }
+            else
+              {
+                nerr("Packet too short (lease time missing)\n");
+              }
             break;
 
           case DHCP_OPTION_END:
             return type;
         }
 
+      if (optptr + 1 >= end)
+        {
+          break;
+        }
+
       optptr += optptr[1] + 2;
     }
 
@@ -385,13 +431,15 @@ static uint8_t dhcpc_parseoptions(FAR struct dhcpc_state *presult,
 static uint8_t dhcpc_parsemsg(FAR struct dhcpc_state_s *pdhcpc, int buflen,
                               FAR struct dhcpc_state *presult)
 {
-  if (pdhcpc->packet.op == DHCP_REPLY &&
+  if (buflen >= 44 && pdhcpc->packet.op == DHCP_REPLY &&
       memcmp(pdhcpc->packet.xid, xid, sizeof(xid)) == 0 &&
       memcmp(pdhcpc->packet.chaddr,
              pdhcpc->ds_macaddr, pdhcpc->ds_maclen) == 0)
     {
       memcpy(&presult->ipaddr.s_addr, pdhcpc->packet.yiaddr, 4);
-      return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4], buflen);
+      return dhcpc_parseoptions(presult, &pdhcpc->packet.options[4],
+                                buflen -
+                                (offsetof(struct dhcp_msg, options) + 4));
     }
 
   return 0;

Mime
View raw message